resize事件需防抖以避免高频触发导致卡顿;通过闭包保存timerId实现轻量防抖,延迟设为100–250ms,推荐结合requestAnimationFrame对齐渲染帧。

在窗口大小调整(resize)事件中直接执行重绘逻辑会导致高频触发,严重拖慢页面性能。防抖(debounce)是常用优化手段——它让回调只在用户停止调整窗口后的一段延迟内执行一次。
为什么 resize 事件需要防抖
resize 在浏览器缩放、拖拽窗口边框等操作中会连续触发数十甚至上百次。若每次触发都调用 getBoundingClientRect()、修改 DOM 或触发 requestAnimationFrame,极易造成布局抖动(layout thrashing)和强制同步重排(forced synchronous layout),尤其在低端设备上明显卡顿。
实现一个轻量防抖函数
无需引入 Lodash,几行代码就能写出可靠防抖:
注意:必须保存定时器引用,避免多次触发导致旧定时器被覆盖而失效
- 使用闭包或模块变量保存
timerId,确保每次调用能清除前一次未执行的定时器 - 延迟时间建议设为
100–250ms:太短起不到节流作用,太长会让响应显得迟钝 - 若需立即执行首次触发(leading edge),可额外支持,但 resize 场景通常只需尾部执行(trailing edge)
绑定到 resize 事件的标准写法
推荐使用 addEventListener + 匿名函数包装防抖回调,避免重复绑定或内存泄漏:
function debounce(fn, delay) {
let timerId;
return function (...args) {
clearTimeout(timerId);
timerId = setTimeout(() => fn.apply(this, args), delay);
};
}
const handleResize = debounce(() => {
// 这里放你的重绘逻辑,例如:
// updateChartSize();
// recalculateGridColumns();
}, 160);
window.addEventListener('resize', handleResize);
关键细节:不要在回调里直接写箭头函数并传入 debounce,否则无法正确清除定时器
进阶建议:结合 requestAnimationFrame 提升渲染效率
若重绘逻辑涉及样式计算或 DOM 更新,可将防抖后的回调进一步包裹进 requestAnimationFrame,确保在下一次绘制帧开始前执行,避免错过帧或触发额外重排:
const handleResize = debounce(() => {
requestAnimationFrame(() => {
// 执行测量、更新 class、调整 canvas 尺寸等
});
}, 160);
这种组合既控制了事件频率,又对齐了浏览器渲染节奏,是现代前端处理 resize 的推荐模式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











