为啥通过 AJAX 无限滚动加载的内容的高度在加载后没有正确测量?
Posted
技术标签:
【中文标题】为啥通过 AJAX 无限滚动加载的内容的高度在加载后没有正确测量?【英文标题】:Why is the height of content loaded through AJAX infinity scroll not measured correctly after loading?为什么通过 AJAX 无限滚动加载的内容的高度在加载后没有正确测量? 【发布时间】:2016-03-28 08:47:22 【问题描述】:我正在使用 无限滚动(通过 AJAX 实现)将由图片或视频组成的帖子加载到我网站的主 div 中。该系统的工作方式与任何流行的 meme 网站非常相似。
问题:每个帖子的左侧都有一个正文部分,右侧有一个社交按钮容器。我希望社交按钮容器在用户滚动时与帖子正文一起移动,并停在父 div 的底部,以便他们在到达帖子底部时可以喜欢它。问题是 一些 通过我的 AJAX 滚动功能加载的帖子似乎没有正确计算父母的高度,并且当浏览器窗口到达他们。 Here is a visual illustration 所需的行为。
实现:我无法编译一个可以工作的 jsFiddle,它可以模拟 AJAX 请求加载图像和视频以及“滚动”调用的行为。这是我的实现和调试尝试:
每篇文章的结构如下:
<div class="article-container">
<div class="article-body-left"><img src="..."></div>
<div class="social-buttons-right">
<div class="facebook-button">...</div>
</div>
</div>
每个 AJAX 请求完成后,我尝试使用 on 'scroll' 来确定每个社交按钮容器的位置,并在用户使用 ajaxComplete() 滚动时修改它们:
$(document).ajaxComplete(function()
bind_sticky_boxes();
);
function bind_sticky_boxes()
$(window).on('scroll', function()
$('.social-buttons-right').not('.following').each( function()
var element = $(this).addClass('following'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = originalY+parent_height-element.height() -10;
$(window).on('scroll', function(event)
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10)
element.css('position','absolute');
element.css('top',(scrollTop - parent_offset + 10) + 'px');
element.css('right', '0px');
if (scrollTop > (destination -10 ) )
element.css('top',parent_height-element_height);
element.css('right', '0px');
element.css('bottom', '0px');
else
element.css('position','relative');
element.css('top','initial');
element.css('left', 'initial');
element.css('right','initial');
element.css('bottom', 'initial');
);
);
);
调试和注意事项:滚动功能在第一次 AJAX 请求后工作正常,但之后由于某些 .social-buttons-right 不跟随而有些中断沿着文章正文或在站点滚动期间直接跳到父 div 的底部。
当我检查行为异常的元素时,我发现它们都有“.following”,这意味着滚动功能已经找到它们,但它们也得到了 bind_sticky_boxes 给它们的 css 属性的错误组合。
这让我相信它与图像加载期间的高度计算有关,所以我使用 requestanimationframe() 稍等片刻,然后 setTimeout(function()..,2000) 触发滚动绑定更晚。这些都没有真正解决问题(后者无论如何都不是解决方案。)我也尝试过早一点触发 AJAX 请求,但由于某种原因,这似乎产生了更糟糕的效果。
更新:我现在确信问题与父身高计算有关。我将 css 属性交换为具有相同属性的唯一类,并注意到行为不端元素的类更改几乎总是发生在父 div 的开头,我认为这强烈表明它的高度在之后没有正确计算将其附加到主 div。
关于我的无限卷轴。我不包括整个 AJAX,因为我认为它与问题没有严格的关系。但我以这种方式将内容附加到主 div:
success: function(response)
if ( max_page >= paged)
$('#page').append(response.content);
else
has_content = false;
loading = false;
页面加载完成后,我开始无限滚动。当用户到达 ID load-more-posts 的元素时触发 AJAX 请求,该元素位于主包装器下方。
$(window).on('load',function()
$(window).on('scroll', function()
var element_position = $('#load-more-posts').offset().top + $('#load-more-posts').outerHeight() - window.innerHeight;
var y_scroll_pos = $(window).scrollTop();
if( ( y_scroll_pos >= element_position ) && !loading)
paged++;
load_more_posts();
);
);
【问题讨论】:
@Mayank 我什至无法正确布局。 jsFiddle 增加了某种我无法摆脱的边距。我希望 .post-body 留在左边, .post-social 放在右边,但 .post-body 中有一个我无法删除的边距。两者都在 .post-container 内......不知道为什么边距是那里有jsfiddle.net/hu0om6d3/4 我没有看到您的 AJAX 存在问题,但我发现您的 CSS 存在问题。你能发布一张图片来展示你想要的样子吗? @LGSon 抱歉,我要去吃圣诞晚餐了。明天会发布更多信息。我将补充一点,我将 css 放在单独的类中并交换它们,这样它们就不会混合,这对于第一个 ajax 请求很有效。只是在我在以下请求中附加新帖子后,父级高度似乎计算得很差,好像里面没有图像,社交按钮容器只是跳到父级的末尾。因此,为什么我猜它与图像加载有关。明天我会更详细地改进这个问题。 检查了您的图片并重新阅读了您的问题。在我看来,当计算发生时,元素引用可能指向错误的帖子,就像你说它要么停留在顶部要么跳到底部。如果它引用了一个高于或低于视图的元素,那将是预期的行为。这可能有助于调试,如果您需要进一步的帮助,则需要一个有效的 sn-p 来查看发生了什么。 有了这些知识,您现在知道如何解决它了,对吧? .. 无论如何,这里有一篇文章可能有助于了解何时加载图像:***.com/questions/821516/… 【参考方案1】:问题是目前各种高度/位置属性的计算绑定到滚动事件,该事件可能在通过 AJAX 附加的图像加载之前触发,因此计算不正确。为了解决这个问题,我必须将它绑定到加载事件,以确保图像可以使用。
$('.article-body-left img').one('load', function()
var element = $(this).parent().parent().find('.social-buttons-right'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = parent_offset+parent_height-element.height() -10;
//alert("Element offset: "+originalY+"\nParent offset: "+parent_offset+"\nParent height: "+parent_height+"\nElement height: "+element_height+"\nDestination: "+destination);
$(window).on('scroll', function(event)
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10)
element.removeClass('above').removeClass('below').addClass('along');
element.css('top',(parseInt(scrollTop - parent_offset + 10)) + 'px');
if (scrollTop > (destination -10 ) )
element.removeClass('above').removeClass('along').addClass('below');
element.css('top','');
else
element.removeClass('below').removeClass('along').addClass('above');
element.css('top','');
);
).each(function()
if(this.complete) $(this).load();
);
CSS:
.along
position: absolute;
right : 0px;
.below
position: absolute;
right: 0px;
bottom: 0px;
.above
position: relative;
【讨论】:
以上是关于为啥通过 AJAX 无限滚动加载的内容的高度在加载后没有正确测量?的主要内容,如果未能解决你的问题,请参考以下文章