函数节流的核心是“稳执行”而非“少执行”,需配合passive: true和requestanimationframe,避免强制重排与重绘,轻量逻辑外移至web worker或虚拟滚动。

函数节流(Throttle)在复杂可视化应用中不是为了“压低响应”,而是把滚动事件对齐到浏览器的渲染节奏,确保视觉反馈连续、计算不挤占主线程。关键不在“少执行”,而在“稳执行”——每 16ms 最多处理一次,刚好匹配 60FPS 刷新周期。
节流必须配合 passive: true
现代浏览器对未声明 passive: true 的 scroll 监听器会强制同步阻塞滚动,哪怕回调里只有一行 console.log。这是比节流更底层的性能开关:
- 不加 passive,滚动卡顿是必然的,节流效果被抵消
- 加了 passive 后,浏览器可异步处理滚动,节流才能真正起效
- 写法示例:window.addEventListener('scroll', handler, { passive: true })
用 requestAnimationFrame 实现精准节流
比 setTimeout 或时间戳轮询更可靠,因为它与屏幕刷新强绑定,不会因 JS 阻塞而跳帧:
- 记录上一次执行时间,仅当间隔 ≥ 16ms 才触发下一帧处理
- 把实际逻辑包裹在 requestAnimationFrame 内,交由浏览器统一调度
- 避免在回调中读取 offsetHeight、getBoundingClientRect() 等触发强制重排的属性
节流回调里只放轻量逻辑
节流解决的是“太密”,不是“太重”。以下操作即使节流了也会拖垮帧率,必须移出:
- 图片解码或大尺寸 Canvas 绘制 → 改用 Image.decode() + loading="lazy"
- 长列表全量 DOM 更新 → 改用虚拟滚动,只渲染可视区 5–10 个 item
- 复杂状态计算(如实时 filter 数组、格式化大量日期)→ 移到 Web Worker 或防抖后执行
滚动临界判断要兼顾首尾
可视化场景常需“刚滚就响应 + 停止后兜底”,比如吸顶导航显隐、懒加载触达临界点:
- 推荐配置:{ leading: true, trailing: true }
- leading = true:第一次滚动立即执行(如 sticky 导航立刻隐藏)
- trailing = true:停止后补调一次(确保最后位置准确触发临界逻辑)
- 注意:不要直接传 event 对象进节流闭包——滚动事件对象是复用的,节流后拿到的可能是过期引用










