JS中resize事件必须防抖,因拖拽窗口每秒触发数十次,不防抖会导致卡顿、CPU飙升;推荐150ms防抖,用闭包定时器、matchMedia判断断点、类名控制状态,并在组件卸载时移除监听。

在 JS 项目中处理窗口大小重置(resize事件),防抖不是可选项,而是必须项——因为拖拽窗口时每秒可能触发几十次 resize,不加控制会直接导致布局计算卡顿、CPU 升高、甚至页面假死。
为什么 resize 必须防抖
浏览器在用户拖动窗口边框过程中持续派发 resize 事件,而非只在结束时触发。实测中,一次中等速度的窗口拉伸可能触发 40–80 次事件。若每次都在回调里执行 DOM 操作或样式重算,性能开销极大。防抖确保只响应“稳定后的尺寸”,逻辑更合理,体验更顺滑。
推荐的防抖实现方式
不用造轮子,但要理解关键点。以下是最轻量、兼容性好、可直接落地的写法:
- 用
window.addEventListener('resize', handler)绑定,避免覆盖已有监听器 - 防抖延迟设为 150ms 左右:太短(如 50ms)仍可能误判“未稳定”,太长(如 500ms)会让响应显得迟钝
- 定时器变量必须闭包保存(如
let resizeTimer = null),每次触发先clearTimeout(resizeTimer),再设新定时器 - 回调函数内通过
window.innerWidth和window.innerHeight获取最新视口尺寸,不要缓存旧值
结合布局调整的典型用法
拿到稳定尺寸后,别硬编码改样式,优先走语义化、可维护的路径:
- 用
matchMedia判断断点,比手动比数字更清晰:if (window.matchMedia('(max-width: 768px)').matches) { /* 切换移动端逻辑 */ } - 切换 CSS 类名控制整体状态,例如:
document.body.classList.toggle('is-mobile', width - 需要动态计算时,把布局逻辑封装成独立函数(如
updateGridLayout()),防抖回调里只调它,便于测试和复用
别忘了清理监听器
尤其在单页应用(SPA)中,组件卸载或路由跳转时若不移除 resize 监听,会导致内存泄漏和逻辑错乱:
- 不能用匿名函数绑定,否则无法
removeEventListener - 保存 handler 引用,例如:
const handleResize = debounce(() => { /* ... */ }, 150);window.addEventListener('resize', handleResize); - 在组件销毁钩子(如 Vue 的
beforeUnmount,React 的useEffect清理函数)中调用:window.removeEventListener('resize', handleResize);


















