防抖与节流
防抖
防抖: 动作发生一定时间后再执行,如果在这段时间内再次触发,则需要重新等待一段时间后再触发。
就像是电梯门一样,当门感应到有人进来时会计时关门,如果这期间有感应到有人进来,那就重新计时。
防抖函数:
function debounce(func, delay) {
let _innerTimer = null;
return function debounce_inner(...args) {
clearTimeout(_innerTimer);
_innerTimer = setTimeout(() => { // 箭头函数控制this
func(...args);
}, delay);
}
}
示例:
Result
Loading...
Live Editor
节流
节流:动作发生后一定时间后再执行,如果在这段时间内再次触发,则忽略该动作,而不是重新计时;直到执行完成,如有触发才会再次响应。
节流函数:
function throttle(func, delay) {
// 或者使用 Date.now()
let timer = false;
return function throttle_inner(...args) {
if(timer) {
return;
}
timer = true;
setTimeout(() => {
func(...args);
timer = false;
}, delay);
}
}
示例:
Result
Loading...
Live Editor
应用场景
防抖的应用场景: (连续的事件,只需触发一次回调的场景)
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小
resize
。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流的应用场景: (间隔一段时间执行一次回调的场景)
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
这样,在某些特定的工作场景,我们就可以使用防抖与节流来减少不必要的损耗。
参考资料
扩展
重绘与回流
- 重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要 UI 层面的重新像素绘制,因此损耗较少。
- 回流(reflow):又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。
常见的重绘操作有:
- 改变元素颜色
- 改变元素背景色
- 。。。
常见的回流操作有:
- 页面初次渲染
- 浏览器窗口大小改变
- 元素尺寸/位置/内容发生改变
- 元素字体大小变化
- 添加或者删除可见的 DOM 元素
- 。。。
回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。
回流会使浏览器开销增大,所以我们通过 防抖和节流 来防止这种增大浏览器开销的事情。