如何从简单的jQuery addClass / remove Class中删除jank

时间:2016-04-10 23:12:36

标签: jquery frame-rate

我的网站上有一个简单的脚本,在用户开始滚动后会在导航栏中添加一个css类,当它们回到页面顶部时会将其删除。

但是,这会导致大量的jank(fps滞后),并且100%的效果不值得。

有没有办法优化这个或让它工作而不会导致jank?

$(window).scroll(function() {    
    var scroll = $(window).scrollTop();
    var navbar = $('#navbar');

    if (scroll >= 40) {
        navbar.addClass("navbar-border");
    } else {
        navbar.removeClass("navbar-border");
    }
});

如果没有,我会将其删除。

谢谢!

2 个答案:

答案 0 :(得分:2)

您的代码可能每秒访问DOM一次,这是性能问题的原因,为了提高性能,您可以限制滚动事件,以便通过使用首先取消绑定Scroll事件的Timeout来减少执行代码然后在延迟(阈值)后绑定它,增加阈值将导致代码执行频率降低。

var navbar = $('#navbar-border');
var threshold = 100; // in milliseconds

function borderControl() {
  console.log("run");
  var scroll = $(window).scrollTop();
  if (scroll >= 40) {
    navbar.addClass("navbar-border");
  } else {
    navbar.removeClass("navbar-border");
  }
}

function setScrollTimer() {
  unbindScroll();
  scrollTimer = window.setTimeout(function() {
    bindScroll()
  }, threshold);
}

function unbindScroll() {
  $(window).unbind("scroll");
}

function bindScroll() {
  $(window).scroll(function(e) {
    setScrollTimer();
    borderControl();
  });
}
bindScroll();

https://jsfiddle.net/sjmcpherson/Lugrukwm/

答案 1 :(得分:0)

您可以通过将结果存储在全局变量中或至少在滚动回调之外保留的变量来缓存处理结果,以减少处理频率。

在回调开始时,我们没有太大的改进空间。

var navbar = $('#navbar');
var navborder = false;
$(window).scroll(function() {    
    var scroll = $(window).scrollTop();

    if (!navborder && scroll >= 40) {
      navborder = true;
      navbar.addClass("navbar-border");
    } else if(navborder && scroll < 40) {
      navborder = false;
      navbar.removeClass("navbar-border");
    }
});

http://codepen.io/t3hpwninat0r/pen/yOvaGN

或者您可以禁用滚动位置检查,然后设置计时器以在短暂延迟后重新启用它

var scrollTimer = 0;
$(window).scroll(function() {
    clearTimeout(scrollTimer);
    scrollTimer = setTimeout(function() {
      var scroll = $(window).scrollTop();
      var navbar = $('#navbar');

      if (scroll >= 40) {
        navbar.addClass("navbar-border");
      } else {
        navbar.removeClass("navbar-border");
      }
    }, 100);
});

http://codepen.io/t3hpwninat0r/pen/BKYLMb

如果用户继续滚动,定时器将继续重启,该功能仅在100ms定时器完成时运行。此示例仅为代码添加4行而不进行任何其他更改。

我从这个答案中获取(阅读:抄袭)代码:https://stackoverflow.com/a/14092859/1160540