防抖可有效优化resize事件频繁触发导致的卡顿问题,其核心是每次触发时清除前次定时器并重设延迟执行,仅保留最后一次触发后的执行;推荐使用addeventlistener绑定预创建的防抖函数,并在单页应用中支持cancel方法以避免内存泄漏。

窗口大小调整(resize)事件触发非常频繁,尤其在拖拽浏览器边框时,每秒可能触发数十次。如果每次触发都执行重排、重绘或复杂计算(比如重新计算布局、更新图表尺寸),会导致页面卡顿。防抖(Debounce)能有效减少实际执行次数——只保留最后一次触发后的延迟执行,丢弃中间的冗余调用。
防抖函数的基本实现
核心思路是:每次触发时清除上一次的定时器,再设置一个新的延迟任务。只有当连续触发停止超过设定时间后,函数才真正执行。
一个轻量、可复用的防抖函数示例如下:
function debounce(func, wait) {
let timeout;
return function executedFunction() {
const later = () => {
clearTimeout(timeout);
func.apply(this, arguments);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
绑定到 resize 事件的正确写法
注意两点:一是防抖函数需提前创建(避免每次事件都新建闭包),二是推荐使用 addEventListener 而非 onresize,便于后续移除。
- 将需要优化的逻辑(如更新容器宽度、重绘 Canvas)封装为独立函数
- 用
debounce包裹它,生成防抖版本 - 把防抖版本传给
addEventListener
function handleResize() {
console.log('窗口尺寸:', window.innerWidth, 'x', window.innerHeight);
// 这里放你的实际逻辑,比如调整图表、响应式栅格等
}
const debouncedResize = debounce(handleResize, 250);
window.addEventListener('resize', debouncedResize);
// 清理(可选,比如组件卸载时)
// window.removeEventListener('resize', debouncedResize);
更现代的写法:使用可取消的防抖(带 cleanup)
在单页应用中,组件可能随时销毁。为避免内存泄漏或对已卸载 DOM 操作,建议防抖函数支持手动取消:
function debounce(func, wait) {
let timeout;
const debounced = function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
debounced.cancel = () => clearTimeout(timeout);
return debounced;
}
const debouncedResize = debounce(handleResize, 250);
window.addEventListener('resize', debouncedResize);
// 卸载时调用
// debouncedResize.cancel();
实际优化效果与注意事项
250ms 是常见阈值,兼顾响应性与性能;若对实时性要求极高(如拖拽缩放预览),可降至 100ms;若只是适配布局,300–400ms 更稳妥。
- 不要在防抖函数内直接操作未挂载的 DOM 节点(如 React 组件已 unmount)
- 避免在
debounce外层包裹箭头函数(会破坏this和arguments的正确传递) - 移动端 Safari 的
resize行为略有差异(比如横竖屏切换可能不触发),必要时可监听orientationchange作为补充
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











