resize事件需节流,因其拖拽时高频触发易致卡顿;节流通过时间窗口控制执行频率,推荐requestAnimationFrame实现,再结合减少布局强制回流等优化效果更佳。

窗口大小调整(resize)事件在拖拽浏览器边框时会高频触发,有时每秒达数十次。若每次触发都执行重排、重绘或重新计算布局的逻辑,极易引发页面卡顿、掉帧甚至主线程阻塞。节流函数正是为这类场景设计的——它不阻止事件发生,而是控制处理函数的执行节奏,确保单位时间内最多执行一次。
为什么 resize 需要节流?
resize 是典型的“连续型高频事件”:用户拖动窗口边缘时,浏览器持续派发事件,但人眼感知不到毫秒级变化,也不需要每毫秒都响应。直接绑定复杂逻辑(如重算栅格列数、更新 canvas 尺寸、重定位浮层)会导致:
- 重复 DOM 查询与样式计算(Layout)
- 频繁触发重绘(Paint),尤其含 transform 或 opacity 变更时
- 若内部含 fetch 或复杂计算,还会拖慢主线程,影响滚动等其他交互
节流的核心策略:时间窗口 + 执行约束
对 resize 的节流,关键不是“延迟”,而是“控频”。常用两种实现思路:
- 时间戳版:记录上一次执行时间,当前时间减去该时间 ≥ 设定间隔(如 100ms),才允许执行并更新时间戳。适合需快速响应的场景,首次触发即可能立即执行
-
定时器版:用
setTimeout设置延迟,若在延迟期内再次触发,则清除旧定时器、重设新定时器。保证最后一次触发后等待指定时间再执行,更侧重“稳定收尾”
推荐使用 requestAnimationFrame 节流
比传统定时器更优:它天然与浏览器渲染帧率同步(约每 16.7ms 一帧),且后台标签页自动暂停,不浪费资源。代码简洁,执行时机精准:
示例:
function rafThrottle(fn) {<br>
let pending = false;<br>
return function(...args) {<br>
if (pending) return;<br>
pending = true;<br>
requestAnimationFrame(() => {<br>
fn(...args);<br>
pending = false;<br>
});<br>
};<br>
}然后:
window.addEventListener('resize', rafThrottle(handleResize));
配合实际优化点一起用效果更好
节流只是第一步,还需减少单次执行的开销:
- 把 layout 触发操作(如
offsetWidth、getBoundingClientRect())集中读取,避免强制同步回流 - 用 CSS 变量或
transform替代修改top/left/width等触发布局的属性 - resize 中避免新增 DOM 或复杂 JS 计算;可先缓存尺寸,交由
IntersectionObserver或ResizeObserver异步处理容器变化


















