这不是啥新问题,只不过最近又重新回顾了一下这个问题
解决 onscroll
每次计算导致的性能问题
onscroll
是最典型的需要进行防抖
或者节流
的处理问题
最近有人问到我,防抖
和节流
有什么不同
无论是防抖还是节流最终的目的都是避免回调函数中的处理每次都执行
。
防抖的思想如下:
只有空闲的时候才去处理回调函数
setTimeout
主要是为了使得处理方法挂在事件循环队列后面,保证事件循环队列中的前面的一些操作有时间进行// 计时器
var timer = false;
//
window.onscroll = function(){
clearTimeout(timer);
timer = setTimeout(function(){
console.log("防抖");
console.log(new Date());
},300);
};
为什么要clearTimeout
每次onscroll的时候,先清除掉计时器.如果不清楚,会导致多次触发的时候,其实是把好多次的处理方法放在某个时间点后一起执行。
比如下面:
for (var i = 0; i < 10; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 3000);
})(i);
}
上面代码在3秒后会一起输出 1,2,3,4,5,6,7,8,9
而下面的代码,只会输出9
var timer2 = false;
for (var i = 0; i < 10; i++) {
clearTimeout(timer2);
(function (i) {
timer2 = setTimeout(function () {
console.log(i);
}, 3000);
})(i);
}
这是因为,每次我将上次的timer
给清除掉了,也就是我如果后面同样有处理函数的话,那我就用后面的定时器。
前面定时器没啥用了,所以直接clearTimeout保证了这种实现。
在解决onscroll问题的时候,如果自己观察console可以发现,防抖保证了滚动停止的时候,才会进行处理,因为滚动停止了,没有scroll事件了,最后一次timer会被保留,从而进行调用
节流思想如下:
flag
元素和setTimeout
实现在一定时间内,只执行一次方法防抖中,每次其实都会生成定时器,只不过定时器还没到时间(这个时间是指将事件挂在事件循环队列后面的时间),就把上面的定时器给清掉了。
而节流则是到了一定的时间,我才进行定时器,否则我不进行定时器。
比如:
var flag = true;
window.onscroll = function(){
if(!flag) return false;
flag = false;
setTimeout(function(){
console.log("节流" + new Date());
flag = true;
},300);
};
这个还是比较直观的:
flag
,默认是true
,这个标志位控制是否能够进行定时器.flag = true
表示,本段时间已经结束了,可以进行下一次的定时器。产生的效果如下:
第一次执行定时器后,300毫秒后,将事件挂在事件循环队列后,而在这个过程中,(包括300ms及事件循环队列循环到挂上事件的时间段)flag 都是 false,则不会多次设置定时器,一旦事件执行了,则 flag 变成 true,能够设置下一次定时器
下面的代码虽然无法做到节流(不是无法做到节流,for太快了,和onscroll是不一样的),但是可以明显的看到一个等待期
并且最后只能输出一个0
,因为第一次执行之后,由于for太快,在等待(等待概念查看上面的解释)的时间中,for已经结束了。
var flag = true;
for (var i = 0; i < 1000; i++) {
if (!flag) {
console.log("等待期");
continue;
}
flag = false;
(function (i) {
setTimeout(function () {
console.log(i);
flag = true;
}, 0);
})(i);
}
示例中每次滚动结束后才会触发一次alert
http://jsrun.net/VviKp/edit?utm_source=website
如果较长点时间快速滚动不停下,会执行两次,这就是节流的周期。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。