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

如何从简单jQuery addClass/remove类中删除jank,jquery,frame-rate,Jquery,Frame Rate,我在我的网站上有一个简单的脚本,在用户开始滚动后将css类添加到导航栏中,并在用户返回页面顶部时将其删除 然而,这造成了大量的jank(fps延迟),100%的性能不值得受到影响 有没有一种方法可以优化这一点,或者让它在不引起jank的情况下工作 $(window).scroll(function() { var scroll = $(window).scrollTop(); var navbar = $('#navbar'); if (scroll >=

我在我的网站上有一个简单的脚本,在用户开始滚动后将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");
    }
});
如果没有,我就把它拿走


谢谢

您的代码可能每秒访问DOM 100次,这是性能问题的原因。为了提高性能,您可以限制scroll事件,以便它通过使用一个超时来执行代码,该超时首先解除scroll事件的绑定,然后在延迟后将其绑定(阈值),增加阈值将导致代码执行频率降低

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

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

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

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

从回调开始,我们没有太多的改进空间

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");
    }
});

如果用户继续滚动,计时器将继续重新启动,并且该功能将仅在100ms计时器完成后运行。本例仅向代码中添加4行,没有任何其他更改


我从这个答案中获取了(阅读:剽窃)代码:

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

从回调开始,我们没有太多的改进空间

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");
    }
});

如果用户继续滚动,计时器将继续重新启动,并且该功能将仅在100ms计时器完成后运行。本例仅向代码中添加4行,没有任何其他更改


我从这个答案中获取了(阅读:剽窃)代码:

如果您使用的是lodash,那么我们就可以使用
throttle
函数来实现这一点。如果您使用的是lodash,那么我们可以使用
throttle
函数来实现这一点。第二个答案可能根本不会触发setTimeout函数,因为scrollTimer在超时函数有机会执行之前被清除。它将始终被清除,但将始终被重新创建。类切换可能会延迟到一个不理想的时间,但函数不可能不运行,因为每次清除计时器时,它都会重新创建,这正是我试图理解的,您已经给出了更好的解释第二个答案可能根本不会触发setTimeout函数,因为scrollTimer在Timeout函数有机会执行之前被清除。它将始终被清除,但它将始终被重新创建。类切换可能会延迟到不理想的时间,但函数不可能不运行,因为每次清除计时器时,它都会重新创建。这正是我试图理解的,您已经给出了更好的解释