resize事件必须加防抖,因其拖拽过程中每秒触发数十次,直接执行DOM重排或echarts.resize()会导致频繁回流重绘而卡顿;防抖确保用户停手后仅执行一次。

窗口大小调整(resize)事件天然高频,拖拽浏览器边框时可能每秒触发数十次。直接在回调里做 DOM 重排、echarts.resize() 或计算布局,极易引发卡顿。防抖是首选处理方式——它确保只在用户真正“停手”后执行一次。
为什么 resize 必须加防抖
resize 不像 click 那样有明确终点,它会在整个拖拽过程中持续触发。实测表明:一次普通窗口缩放可能触发 50~200 次事件。若每次都在回调中调用 this.chart.resize() 或重算栅格列数,浏览器会反复重绘、回流,用户感知就是页面发卡、鼠标滞后。
标准防抖函数写法(带 this 和参数支持)
下面是一个生产环境可用的 debounce 实现,能正确保留 this 上下文和事件参数:
function debounce(func, delay = 300) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
}
resize 事件绑定示例
以适配 ECharts 图表为例:
- 获取图表实例后,定义防抖后的 resize 处理函数:
const debouncedResize = debounce(() => chart.resize(), 300); - 绑定到 window:
window.addEventListener('resize', debouncedResize); - 组件卸载或图表销毁时,记得清理定时器(可选增强):
return () => clearTimeout(timer); // 在闭包中暴露 timer 或改用 cancelable 版本
常见误区提醒
不要用 window.onresize = debounce(...) 这种赋值写法——它会覆盖其他监听器,且无法移除;优先用 addEventListener。延迟时间一般设 200~400ms:太短起不到过滤作用,太长会让用户感觉响应迟钝。ECharts 官方文档也明确建议对 resize 使用防抖处理。











