防抖(debounce)指的是:事件连续不断触发,只响应最后一次。
实际的运用场景是:滚动、鼠标高频点击、窗口大小连续变化、input输入等事件,会频繁触发响应函数,但我们不需要这么频繁的响应。我们觉得这一波高频事件完成后再做一次响应就行了。
因此防抖的具体过程是:事件触发后设置“沉默”定时器,并清除之前的定时器,“沉默”一定时间(不会太长)后,定时器到期并执行动作。
这篇文章的时间线图片可以帮助理解:js防抖和节流
先不考虑封装函数。针对scoll的防抖应该是这样:
<script>
document.addEventListener('DOMContentLoaded', function () {
var timer = null;
document.addEventListener('scroll', function () {
// console.log('scolling');
clearTimeout(timer);
timer = setTimeout(function () {
console.log('scrolled DEBOUNCE');
}, 1000);
});
});
</script>
页面加上大段文字或者<br>就能看出滚动防抖的效果了。(如果你的浏览器不支持监听document的scoll,试试改成window或document.body)
代码中输出“scrolling”那行被注释掉了,如果没注释,就会不断地输出“scrolling”;相比之下,防抖的输出“scrolled DEBOUNCE”只会在滚动停止1000ms后输出一次。
接下来是封装函数。一开始我想到的封装是这样子的:
<script>
document.addEventListener('DOMContentLoaded', function () {
function debounce(dom, eventType, wait, handler) {
var timer = null;
dom.addEventListener(eventType, function () {
clearTimeout(timer);
timer = setTimeout(function () {
handler();
}, wait);
});
}
debounce(document, 'scroll', 1000, function () {
console.log('you stopped scrolling 1000ms ago');
});
});
</script>
形式太low了。看了别人的封装形式,针对响应动作封装就好。参数就是关于做什么动作、延迟多久才做,尽量不改变原有的监听语句形式。改成这样:
<script>
document.addEventListener('DOMContentLoaded', function () {
function debounce(handler, delay) {
var timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(function () {
handler();
}, delay);
}
}
document.addEventListener('scroll', debounce(function () {
console.log('you stopped scrolling 1000ms ago');
}, 500));
});
</script>
完成。防抖我觉得还是比较好理解的,下一篇说节流更绕一点。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。