resize事件需防抖,因窗口拖拽时每秒触发数十次,直接响应会导致重复计算、dom重排及主线程阻塞;防抖确保仅在停止调整后执行最终布局逻辑。

直接在 resize 事件监听中加入防抖,能有效避免窗口拖拽过程中高频触发导致的重复计算和重绘。核心是让浏览器只在用户停止调整尺寸后的一小段时间才执行布局或渲染逻辑。
为什么 resize 需要防抖
浏览器在用户拖动窗口边框时,每秒可能触发数十次 resize 事件。若每次都在回调里调用 chart.resize()、重新计算栅格列数或触发 setState,不仅造成大量无意义 DOM 重排,还可能阻塞主线程。防抖确保只响应“最终尺寸”,而不是“中间过程”。
手写一个轻量防抖函数
不需要引入 Lodash,几行代码就能搞定:
const debounce = (fn, delay = 250) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
使用方式:
- 在组件挂载时绑定:window.addEventListener('resize', debounce(handleResize, 300))
- 务必在卸载前移除监听器,否则会内存泄漏
- 如果 handleResize 依赖 this 或闭包变量,注意用箭头函数或 bind 绑定上下文
在 React 中推荐用自定义 Hook
比手动管理更安全,自动处理清理逻辑:
function useDebouncedResize(callback, delay = 250) {
useEffect(() => {
const handler = debounce(callback, delay);
window.addEventListener('resize', handler);
return () => window.removeEventListener('resize', handler);
}, [callback, delay]);
}
在组件中调用:
- useDebouncedResize(() => { updateChartSize(); }, 300)
- 无需手动存 ref 或清理 timer,Hook 内部已封装
- 支持动态修改 delay,依赖数组更新后自动重建监听
配合 ResizeObserver 更进一步
如果目标不是整个窗口,而是某个容器元素(如图表父容器)的尺寸变化,优先用 ResizeObserver + 防抖组合:
- 它不依赖 window.resize,只监听目标元素盒模型变化,更精准
- 对每个观察目标单独防抖,避免全局 resize 的干扰
- 现代浏览器兼容良好(Chrome 64+、Firefox 69+、Edge 79+)











