节流通过限制回调频次为浏览器争取渲染空闲时间,间接降低重排重绘压力;需配合transform等优化策略、rAF对齐刷新节奏及passive: true开关才能真正生效。

节流本身不直接减少重排重绘,但它通过限制回调执行频次,为浏览器争取出空闲时间来完成渲染任务,从而间接大幅降低滚动过程中的重排重绘压力。
节流如何切断高频调用与重排重绘的强耦合
滚动事件在现代浏览器中每秒可触发 60–120 次。若每次回调都执行 offsetTop、getBoundingClientRect() 或修改 style.left 等操作,就会频繁触发强制同步布局(layout thrashing),导致连续重排。节流把密集调用压缩成稳定节奏(如每 100ms 最多一次),相当于把原本可能每 8ms 就打断一次渲染的 JS 执行,变成有规律的“喘息间隙”——浏览器能在两次节流执行之间完成完整的样式计算、布局、绘制和合成流程。
- 未节流时:1 秒内 100 次
scrollTop读取 +el.style.transform = ...写入 → 多次强制回流 + 连续重绘 → 明显卡顿 - 节流后(100ms):1 秒内约 10 次执行 → 主线程负载下降 90%,渲染帧更稳定
必须配合 DOM 更新策略才真正生效
只加节流却不优化回调内部逻辑,效果非常有限。关键是要让节流后的那一次执行也尽量轻量:
- 用
transform和opacity替代top、left、width等触发布局的属性 - 把多次
offsetHeight、clientWidth读取合并为一次getBoundingClientRect() - 避免在节流回调里反复
querySelector;优先缓存 DOM 引用或使用IntersectionObserver替代滚动监听临界点 - 对复杂计算(如坐标映射、数据过滤)考虑分片处理或移至 Web Worker
requestAnimationFrame 是更优的节流底层
相比 setTimeout 或时间戳方案,requestAnimationFrame(rAF)天然对齐屏幕刷新节奏(通常 60fps,即每 16.7ms 一帧)。它确保 DOM 更新发生在浏览器准备绘制前的最合理时机,避免因定时器误差导致的掉帧或错帧。
立即学习“Java免费学习笔记(深入)”;
- rAF 节流不会被浏览器后台标签页节流,比定时器更可靠
- 它自动跳过非活跃帧,不会强行塞入已超时的任务
- 与 CSS 动画、Canvas 渲染等视觉任务天然协同,减少竞态
别忘了 passive: true 这个关键开关
给滚动监听添加 { passive: true } 选项,能明确告诉浏览器:“这个监听器不会调用 preventDefault()”,从而允许浏览器在不等待 JS 执行的情况下立即响应滚动——这消除了主线程阻塞,是提升滚动流畅度的基础前提。
- 错误写法:
window.addEventListener('scroll', handler)→ 默认 passive = false,可能阻塞滚动 - 正确写法:
window.addEventListener('scroll', handler, { passive: true }) - 若回调中确实需阻止默认行为(极少见),则必须显式设为
{ passive: false }并谨慎评估代价



















