【问题标题】:Debounce jquery scroll events去抖动 jquery 滚动事件
【发布时间】:2016-07-24 18:46:07
【问题描述】:

我只是有一个关于去抖动的一般性问题。我在页面上的不同位置有三个菜单,当它们在滚动时到达距离窗口顶部 85px 的位置时,它们会变得固定。当它们到达顶部时,它们会分层重叠。我目前对每个功能都有一个功能,并且希望尽可能地进行优化。我的阅读表明 .offset.top 计算非常繁琐。

我的问题是:我是不是想多了,在这种情况下有必要去抖动吗?如果我的解释是正确的,那么三个偏移量计算会在滚动时不断执行。任何人都可以提出优化建议或解释为什么不需要。

谢谢。

$(function(){
    // Check the initial Position of the fixed_nav_container
    var stickyHeaderTop0 = $('.fixed_heading_shop').offset().top;

    $(window).scroll(function(){
            if( $(window).scrollTop() > stickyHeaderTop0-85) {
                    $('.fixed_heading_shop').css({position: 'fixed', top: '85px'});  
                    $('.ghost_div0').css({display: 'block'});
            } else {
                    $('.fixed_heading_shop').css({position: 'relative', top: '0px'});
                    $('.ghost_div0').css({display: 'none'});
            }   

    });

  }); 


$(function(){
    // Check the initial Position of the fixed_nav_container
    var stickyHeaderTop1 = $('.fixed_heading_pricetable').offset().top;

     $(window).scroll(function(){
            if( $(window).scrollTop() > stickyHeaderTop1-85 ) {
                    $('.fixed_heading_pricetable').css({position: 'fixed', top: '85px'});  
                    $('.ghost_div1').css({display: 'block'});       
            } else {
                    $('.fixed_heading_pricetable').css({position: 'relative', top: '0px'});
                    $('.ghost_div1').css({display: 'none'});    
            }
         });

}); 



$(function(){
    // Check the initial Position of the fixed_nav_container
    var stickyHeaderTop2 = $('.fixed_heading_layout').offset().top;
     $(window).scroll(function(){    
            if( $(window).scrollTop() > stickyHeaderTop2-85) {
                    $('.fixed_heading_layout').css({position: 'fixed', top: '85px'});  
                    $('.ghost_div2').css({display: 'block'});
            } else {
                    $('.fixed_heading_layout').css({position: 'relative', top: '0px'});
                    $('.ghost_div2').css({display: 'none'});
            }
          });

}); 

【问题讨论】:

    标签: javascript jquery optimization debouncing


    【解决方案1】:

    对于这种情况,我认为这确实是一个偏好问题。看看网站在您给定的情况下如何响应,如果您觉得用户体验受到负面影响,请进行调整。我倾向于限制/去抖动滚动事件。

    您可以采取一些措施来加快滚动处理程序的速度(稍微)。例如,如果您可以使用 id,如 jQuery 的optimizing selectors 指南中所述,例如$('#myElement') 速度很快,因为它使用了document.getElementById

    如果您担心性能,请进行更多细微调整:如果不需要调用,请不要调用调整 css。即如果自上次触发滚动处理程序以来没有任何变化。 (见isFixed布尔)

    $(function(){
      var OFFSET = 85;
      var WAIT = 10;
    
      // Check the initial Position of the fixed_nav_container
      var stickyHeaderTop0 = $('.fixed_heading_shop').offset().top;
      var isFixed = false; // assuming that's the right default value
    
      $(window).scroll(_.throttle(function(){
        if($(window).scrollTop() > stickyHeaderTop0 - OFFSET) {
          if(!isFixed) {
            $('#fixed_heading_shop').css({position: 'fixed', top: OFFSET+'px'});
            $('#ghost_div0').css({display: 'block'});
            isFixed = true;
          }
        }
        else {
          if(isFixed) {
            $('#fixed_heading_shop').css({position: 'relative', top: '0px'});
            $('#ghost_div0').css({display: 'none'});
            isFixed = false;
          }
        }
      }, WAIT));
    });
    

    唯一的重复调用是$(window).scrollTop(),如果您可以组合所有滚动处理程序(3 个?),那么您只需在每个 [节流] 滚动事件中调用一次。

    【讨论】:

    • 我也不排除在父元素上设置 css 类,例如 $('body').toggleClass('fixed-menus', fixedBool); add 在样式表中添加您的规则。
    • 更改为 id 对 chrome 产生了显着影响。去看看 Developer107 的优化建议,然后在上面尝试你的 debounce 方法。
    • 您对组合滚动处理程序有什么建议吗?结合这些方法对我来说有点问题。
    • 得到了 undeline 库和节流工作。我已将您标记为正确,因为从技术上讲,您的回答与我的问题最相关。如果您有任何建议,仍然对组合处理程序感兴趣?
    • @JPB 这是一个example jsfiddle,不确定它是否完全适合您的情况,但希望为您指明正确的方向。
    【解决方案2】:

    无需对 HTML 标记进行任何更改,您就可以稍微优化您的代码:

    $(function(){
    // Check the initial Position of the fixed_nav_container
     var stickyHeaderTop0 = $('.fixed_heading_shop').offset().top;
     var stickyHeaderTop1 = $('.fixed_heading_pricetable').offset().top;
     var stickyHeaderTop2 = $('.fixed_heading_layout').offset().top;
     $(window).scroll(function(){
            if( $(window).scrollTop() > stickyHeaderTop0-85) {
                    $('.fixed_heading_shop').css({position: 'fixed', top: '85px'});  
                    $('.ghost_div0').css({display: 'block'});
            } else {
                    $('.fixed_heading_shop').css({position: 'relative', top: '0px'});
                    $('.ghost_div0').css({display: 'none'});
            }
            if( $(window).scrollTop() > stickyHeaderTop1-85 ) {
                    $('.fixed_heading_pricetable').css({position: 'fixed', top: '85px'});  
                    $('.ghost_div1').css({display: 'block'});       
            } else {
                    $('.fixed_heading_pricetable').css({position: 'relative', top: '0px'});
                    $('.ghost_div1').css({display: 'none'});    
            }
            if( $(window).scrollTop() > stickyHeaderTop2-85) {
                    $('.fixed_heading_layout').css({position: 'fixed', top: '85px'});  
                    $('.ghost_div2').css({display: 'block'});
            } else {
                    $('.fixed_heading_layout').css({position: 'relative', top: '0px'});
                    $('.ghost_div2').css({display: 'none'});
            }
     });
    });
    

    如果你给 if..else 功能相同的三个元素提供一个公共类,那么它会更加优化。 我这里在 JS 中添加了一个 'common' 类,你可以在 html 本身中添加它。

    $(function(){
    // add common class to elements
     $('.fixed_heading_shop, .fixed_heading_pricetable, .fixed_heading_layout').addClass('common');
     var elemArr = [];
     // Check the initial Position of the fixed_nav_container
     $('.common').each(function(index){
            elemArr.push($(this).offset().top);
     })
     $(window).scroll(function(){
         $('.common').each(function(index){
            if( $(window).scrollTop() > elemArr[index]) {
                    $(this).css({position: 'fixed', top: '85px'});  
                    $('.ghost_div'+index).css({display: 'block'});
            } else {
                    $(this).css({position: 'relative', top: '0px'});
                    $('.ghost_div'+index).css({display: 'none'});
            }
         });
     });
    });
    

    【讨论】:

    • 谢谢你,我现在就试试。我只是在学习 javascript,您的代码是了解如何更有效地为某人做事的好方法。我曾尝试组合 if 语句,但语法不正确。
    • 似乎无法正常工作。这个: if( $(window).scrollTop() > elemArr[index]) { 应该是这样的: if( $(window).scrollTop() > $('.common')-85 {
    • 如果对您有所帮助,我很高兴。但是你能告诉你得到的错误是什么吗?
    • ok 这行得通 if( $(window).scrollTop() > elemArr[index]-85) { 对于第一个菜单,但随后的菜单分别在窗口上方再固定 85px?看到这个超级狡猾的 jfiddle(刚刚复制粘贴了我的代码)。当您向下滚动第一个菜单时,修复了 -85,但其余的没有? jsfiddle.net/jpolsonb/g9ezqfgc
    • 我现在明白了。这是因为当我们将所有元素的值存储在 elemArr 中时,第一个元素不是固定定位的。但后来它得到了修复,因此文档高度减少了第一个元素的高度。让我看看能做什么,我会更新 jsfiddle。
    【解决方案3】:

    我想说,与其尝试直接设置 css,不如利用类。

    .fixed_heading_shop,
    .fixed_heading_pricetable {
      position:relative;
      top:0;
    }
    .ghost_div0,
    .ghost_div1 {
      display:block;
    }
    .scroll_trick .fixed_heading_shop,
    .scroll_trick .fixed_heading_pricetable {
      position:fixed;
      top:85px;
    }
    .scroll_trick .ghost_div0,
    .scroll_trick .ghost_div1 {
      display:none;
    }
    
    $(function(){
      var $window = $(window);
      var $body = $('body');
      var top = $('.fixed_heading_shop').offset().top-85;
    
      $window.scroll(function(){
        if( $window.scrollTop() > top) {
          $body.addClass('scroll_trick');
        } else {
          $body.removeClass('scroll_trick');
        }   
      });
    });
    

    【讨论】:

    • 我知道这是如何工作的,只是要固定初始位置的第一个元素在页面下方很远。你能解释一下 var top = $('.fixed_heading_shop').offset().top-85;有效吗?
    • @JPB 这是一个错误。 top 仅在应重新安排脚本以单独考虑时才考虑该特定元素。实际上,应该重新排列 HTML,以便每个 .ghost_div 共享同一个类,每个 .fixed_heading 共享同一个类,并且这些对中的每一对都有自己的包装父级。然后,而不是$body.scroll_trick 将应用于其孩子满足要求的特定包装器。如果你有兴趣,我会看看重新安排代码。
    • 不,没关系,我这次使用了 javascript,但感谢不同的方法,我以后会再来的。
    猜你喜欢
    • 2015-04-12
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-21
    • 1970-01-01
    相关资源
    最近更新 更多