博学谷it学习技术支持
节流和防抖
what
在进行窗口的resize、scroll、输出框内容校验等操纵的时候,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常之差。那么为了前端性能的优化也为了用户更好的体验,就可以采用防抖(debounce)和节流(throttle)的方式来到达这种效果,减少调用的频率
防抖简单的理解为短时间内频繁触发,只执行最后那一次,就是前面的来不及操作了,那就算了,不管了,最后执行那次就可以了
节流其实可以理解为:频繁调用,减少频率过高带来的执行次数,相当于就是控制短时间内的执行次数,及在一段时间内执行一次
why
在绑定scroll、resize事件时,但它发生的时候,它被触发的频率非常高,间隔很近。在日常开发的页面中,事件中涉及到的大量的位置计算、DOM操作、元素重绘等等这些都无法在下一个scroll事件出发前完成的情况下,浏览器会卡帧。
网页生成的时候,至少会渲染(Layout+Paint)一次。用户访问的过程中,还会不断重新的重排(reflow)和重绘(repaint),用户scroll行为和resize行为会导致页面不断的进行重新渲染,而且间隔频繁,容易造成浏览器卡帧
防抖原理
一定在事件触发 n 秒后才执行,如果在一个事件触发的 n 秒内又触发了这个事件,以新的事件的时间为准,n 秒后才执行,等触发事件 n 秒内不再触发事件才执行。
官方解释:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
简单代码演示
//简单的防抖函数
function debounce(func, wait, immediate) {
var timeout;
return function () {
//每次触发scrolle,先清除定时器
clearTimeout(timeout);
//指定多少秒后触发事件操作handler
timeout = setTimeout(func, wait);
};
};
//绑定在scrolle事件上的handler
function handlerFunc() {
console.log('Success');
}
//采用防抖动
window.addEventListener('scrolle', debounce(handlerFunc, 1000));
节流原理
如果持续触发事件,每隔一段时间只执行一次函数。
官方解释:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
简单代码演示
var throttle = function (func, delay) {
var timer = null;
return function () {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function () {
func.apply(context, args);
timer = null;
}, delay);
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000))
图解
找来两张图片,帮助理解一下
图一:
图二:
总结
防抖:原理是维护一个定时器,将很多个相同的操作合并成一个。规定在delay后触发函数,如果在此之前触发函数,则取消之前的计时重新计时,只有最后一次操作能被触发。
节流:原理是判断是否达到一定的时间来触发事件。某个时间段内只能触发一次函数。
区别:防抖只会在最后一次事件后执行触发函数,节流不管事件多么的频繁,都会保证在规定时间段内触发事件函数。