Skip to main content

防抖与节流

防抖

防抖: 动作发生一定时间后再执行,如果在这段时间内再次触发,则需要重新等待一段时间后再触发。

就像是电梯门一样,当门感应到有人进来时会计时关门,如果这期间有感应到有人进来,那就重新计时。

防抖函数:

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 元素
  • 。。。

回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。

回流会使浏览器开销增大,所以我们通过 防抖和节流 来防止这种增大浏览器开销的事情。