跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何利用 函数去抖 (Debounce) 与 节流 (Throttle) 控制高频 DOM 事件的频率

高频DOM事件需用去抖或节流优化:去抖在连续触发结束后延时执行一次,适用于搜索输入、表单校验等关注最终状态的场景;节流则按固定间隔执行,适用于滚动监听、拖拽绘制等需过程反馈的场景。 高频 dom 事件(如
scroll
、
resize
、
mousemove
、
input
)容易在短时间内被反复触发,若每次触发都执行复杂逻辑(比如重排、请求、计算),会导致页面卡顿、资源浪费甚至崩溃。函数去抖(debounce)和节流(throttle)就是专为这类问题设计的轻量级控制策略——它们不阻止事件发生,而是智能调度回调的执行时机。 去抖:等用户“停下来”再响应 去抖适用于关注最终状态的场景。它让函数只在事件连续触发结束后,等待一段空闲时间才执行一次。期间任何新触发都会重置倒计时。 核心逻辑 :用
setTimeout
+
clearTimeout
实现。每次触发时清除旧定时器,新建一个;只有当“静默期”完整过去,函数才真正运行。 典型用途 : 搜索框输入联想(等用户打完字再发请求) 表单实时校验(避免每输一个字就报错) 窗口缩放后重新布局(等用户调好尺寸再重绘) 注意点 :如果用户持续操作(比如一直滚动或输入),回调永远不会执行——这正是它的设计目的,不是 bug。 节流:固定节奏,匀速响应 节流适用于需要过程中持续反馈、但又不能太频繁的场景。它保证函数在单位时间内最多执行一次,不管事件触发多少次。 核心逻辑 :常用两种实现方式: – 时间戳法:记录上一次执行时间,当前时间减去它 ≥ 间隔才执行并更新时间戳; – 定时器法:用标志位(如
timeout
)锁住执行通道,首次触发设定时器,到期才清空标志并允许下一次。 典型用途 : 滚动监听判断是否触底加载(需定期检查,不能只等停) 鼠标拖拽/画布绘制(保持视觉连贯,又不压垮渲染) 抢购按钮防重复点击(限制提交频率,而非禁止所有点击) 注意点 :节流不保证“第一次触发立即执行”,默认是延迟执行;如需首屏立刻响应(前导执行),需额外加判断逻辑。 怎么选?看业务要的是“结果”还是“过程” 一句话判断: – 如果你只关心用户操作结束后的那个状态(比如最终输入内容、最终窗口大小),选 去抖 ; – 如果你需要在操作过程中定期获取信息或反馈(比如滚动中不断计算位置、拖拽中持续更新坐标),选 节流 。 同一个事件也可能混合使用:例如
scroll
既用节流做位置监听,又用去抖做“停止后加载更多” 实际封装时建议加上
this
绑定和参数透传,避免上下文丢失 现代项目可优先使用 Lodash 的
_.debounce
和
_.throttle
,它们已处理了取消、前导/尾随选项等边界情况 简单封装示例(可直接用) 去抖:
function debounce(fn, wait) { let timeout; return function(...args) { clearTimeout(timeout); timeout = setTimeout(() => fn.apply(this, args), wait); }; }
节流(时间戳版):
function throttle(fn, delay) { let last = 0; return function(...args) { const now = Date.now(); if (now - last >= delay) { fn.apply(this, args); last = now; } }; }

相关文章