resize事件需防抖,因其高频触发易导致卡顿;采用250ms延迟执行可避免强制同步布局,提升性能。

页面大小改变(resize事件)非常容易高频触发——用户拖拽窗口边框时,一秒内可能触发几十次。直接在回调里重排布局、更新尺寸或重新渲染,会严重拖慢页面,甚至卡死。用防抖,就是让浏览器“等用户调完再算”,只在最后一次调整结束后的延迟时间点执行布局计算。
为什么 resize 需要防抖
resize 事件没有内置节流机制,原生行为是“只要尺寸变就立刻触发”。哪怕用户只是轻微拖动,也可能连续触发数十次。如果每次都在回调中调用 getBoundingClientRect()、重设 CSS Grid 列数、或重新计算图表 canvas 尺寸,不仅浪费 CPU,还可能引发强制同步布局(Layout Thrashing),导致明显卡顿。
基础防抖实现(推荐延迟执行)
这是最常用、也最适合 resize 场景的写法:用户停止调整 250ms 后才执行布局逻辑。
- 定义一个防抖函数,接收目标函数和延迟时间(如 250ms)
- 把原本写在
resize回调里的布局代码,封装进这个函数 - 将防抖后的函数绑定到
window.resize事件上
示例代码:
立即学习“Java免费学习笔记(深入)”;
function debounce(fn, delay) {let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, arguments), delay);
};
}
function updateLayout() {
// ✅ 这里放你的布局逻辑
const width = window.innerWidth;
const height = window.innerHeight;
document.body.style.fontSize = Math.max(14, width / 40) + 'px';
console.log('布局已更新:', width, 'x', height);
}
window.addEventListener('resize', debounce(updateLayout, 250));
注意几个关键细节
实际使用时容易忽略但影响效果的点:
- 延迟时间选 150–300ms 比较合理:太短(如 50ms)起不到过滤作用;太长(如 800ms)会让用户感觉响应滞后
-
避免在防抖函数里做 DOM 查询+修改混合操作:比如先
querySelector再style.xxx =,最好把查询结果缓存或拆成纯计算 + 批量更新两步 -
首次加载也要触发一次布局:防抖只管后续 resize,别忘了在页面初始化时主动调用
updateLayout() -
移动端需额外考虑 orientationchange:Safari 在横竖屏切换时可能不触发 resize,建议同时监听
orientationchange并复用同一防抖函数
可选:立即执行 + 延迟冷却(适合需要即时反馈的场景)
极少数情况(比如全屏弹窗打开瞬间就要适配),你希望第一次 resize 立刻响应,之后再进入防抖节奏。这时可用带 immediate 参数的版本:
let timer = null;
return function () {
if (timer) clearTimeout(timer);
if (immediate) {
const callNow = !timer;
timer = setTimeout(() => timer = null, delay);
if (callNow) fn.apply(this, arguments);
} else {
timer = setTimeout(() => fn.apply(this, arguments), delay);
}
};
}
// 第一次拖动立即生效,之后每 250ms 最多执行一次
window.addEventListener('resize', debounce(updateLayout, 250, true));
不需要复杂工具库,一段闭包 + setTimeout 就能稳住 resize 事件。核心就一句话:别急着算,等用户手停了再说。


















