为什么通过 AJAX infinity scroll 加载的内容加载后高度测量不正确?

Why is the height of content loaded through AJAX infinity scroll not measured correctly after loading?

我正在使用 infinity scroll 将由图片或视频组成的 post 加载到我网站的主要 div(通过 AJAX).该系统的工作原理与任何流行的模因网站非常相似。

问题:每个post左侧都有一个正文部分,右侧有一个社交按钮容器。我希望社交按钮容器在用户滚动时沿着 post 的主体移动,并停在 parent div 的底部,以便他们在到达时可以点赞post 的底部。问题是通过我的 AJAX 滚动函数加载的 post 中的 some 似乎没有正确计算 parents 的高度,它们当浏览器的顶部 window 到达它们时,永远不要移动或直接跳到 parent div 的底部。 Here is a visual illustration 的所需行为。

实现: 我无法编译一个可以模拟 AJAX 请求加载图像和视频的行为的工作 jsFiddle 以及 "scroll" 来电。这是我的实现和调试尝试:

每篇文章结构如下:

<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 在站点滚动过程中,不要跟随文章正文或直接跳到 parent div 的底部。

当我检查我发现的行为不当的元素时,它们都有“.following”,这意味着滚动功能已经找到它们,但它们也得到了 css 属性的错误组合bind_sticky_boxes 给了他们。

这让我相信它与图像加载过程中的高度计算有关,所以我使用 requestanimationframe() 稍等一下,然后 setTimeout(function(){..},2000) 触发滚动绑定甚至更晚。 None 其中确实解决了问题(后一个无论如何都不是解决方案。)我也尝试过早一点触发 AJAX 请求,但这似乎对一些原因。

更新: 我现在确信问题与 parent 高度计算有关。我将 css 属性替换为具有相同属性的唯一 classes,并注意到行为不当元素的 class 更改几乎总是发生在 parent div,我认为这是一个强烈的迹象,表明在将它附加到主要 div.

之后,它的高度没有被正确计算。

关于我的无限卷轴。我不包括整个 AJAX,因为我认为它与该问题没有严格关系。但是我通过这种方式将内容附加到主 div 中:

success: function(response){
            if ( max_page >= paged){
                $('#page').append(response.content);
            } else{
                has_content = false;
            }
            loading = false;
          }

页面加载完成后,我启动无限滚动。 AJAX 当用户到达 id 为 load-more-posts 的元素时请求触发,该元素位于主包装器下方。

$(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();
      }
  });    

});

问题是目前各种 height/position 属性的计算绑定到滚动事件,该事件可能会在通过 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;
}