resize事件需防抖,因其在窗口拖拽时每秒触发数十次,直接响应会频繁引发重排重绘;防抖确保仅在用户停止调整后执行一次最终尺寸处理,降低渲染开销。

页面大小改变(resize事件)会高频触发,每次直接响应都可能引发重排重绘,尤其在图表缩放、布局重计算等场景下,容易造成卡顿。用防抖能确保只在用户停止调整窗口后才执行一次处理逻辑,大幅减少不必要的渲染开销。
为什么 resize 需要防抖
浏览器在拖拽窗口边框时,resize事件每秒可能触发数十次。如果每次都在回调里调用 chart.resize() 或重新计算 DOM 尺寸,就会反复触发回流(reflow)和重绘(repaint)。而多数情况下,你真正需要的只是“最终尺寸”——即用户松手后的那个状态。
防抖实现的关键点
防抖函数本身不难写,但要注意三个细节:
-
清除上一个定时器:每次 resize 触发时都要清除前次未执行的
setTimeout,否则旧任务仍会执行 -
保持 this 和参数上下文:用
func.apply(this, args)确保回调中能正确访问实例方法或 DOM 元素 - 延迟时间设为 150–300ms:太短起不到过滤效果,太长会让用户感觉响应迟钝;150ms 是多数场景下的平衡点
实际使用示例
以 ECharts 图表自适应为例:
// 封装防抖函数
function debounce(func, delay) {<br>
let timer;<br>
return function(...args) {<br>
clearTimeout(timer);<br>
timer = setTimeout(() => func.apply(this, args), delay);<br>
};<br>
}
// 绑定到 resize 事件
const resizeChart = debounce(() => {<br>
if (myChart && myChart.resize) {<br>
myChart.resize(); // 只执行一次<br>
}<br>
}, 150);<br>
window.addEventListener('resize', resizeChart);
配合其他优化更有效
单靠防抖还不够,建议组合以下做法:
- 在
resize回调中避免读取offsetWidth等触发强制回流的属性;如需尺寸,可缓存或用getBoundingClientRect()一次性读取 - 图表类库(如 ECharts、AntV)通常自带
resize节流机制,优先查文档看是否已内置,避免重复封装 - 若涉及大量 DOM 重排(比如网格布局重计算),可在防抖回调里用
requestAnimationFrame再包裹一层,让更新对齐下一帧渲染











