wheel事件必须节流而非防抖,因其需连续响应滚动;推荐RAF+performance.now()实现16–60ms动态节流,并累加delta支持插值渲染。

鼠标滑动事件(mousewheel 或 wheel)在 JS 项目中极易高频触发——滚动一下常产生 10–30 次事件,直接响应会导致重绘卡顿、CPU 占用飙升、甚至 UI 停滞。节流不是“可选优化”,而是保障流畅性的必要手段。
为什么 wheel 事件必须节流,不能防抖
防抖会把整个滚动过程“压到松手才执行一次”,用户拖动滚轮时页面毫无反馈,体验僵硬;而滚动是连续交互,需要即时视觉响应(如内容位移、阴影变化、滚动条同步)。节流能以稳定节奏(如每 16ms 一次)采样 delta 值和时间戳,既抑制无效调用,又维持跟手性。
推荐使用 RAF + 时间戳节流,避免掉帧
单纯用 setTimeout 节流易受事件队列阻塞影响,出现跳帧或延迟累积。应结合 requestAnimationFrame 和高精度时间戳:
- 用
performance.now()记录每次触发时间,判断是否达到最小间隔(如 16ms) - 满足间隔时立即执行处理逻辑,并主动调用
requestAnimationFrame确保渲染在下一帧执行 - 不依赖定时器排队,避免因主线程繁忙导致的执行延迟
节流参数要匹配滚动行为类型
固定设 200ms 或 500ms 会破坏体验。应按实际交互意图调整:
- 普通文档/列表滚动:16–32ms(≈60fps),保证位移平滑不跳变
- 带物理惯性模拟(如触控式滚动):可收紧至 10–16ms,更好捕捉加速度变化
- 仅用于触发懒加载或锚点定位等轻量逻辑:放宽至 40–60ms,减少微小抖动干扰
节流函数需保留最后一次 delta 并支持插值
滚动过程中,用户可能在单次节流间隔内移动了较大距离(尤其高速滚轮)。若只取当次 delta,会丢失中间量,造成“瞬移”感。建议:
- 在节流外持续记录原始
event.deltaY累加值 - 节流回调中传入累计 delta 和时间戳,供动画逻辑做线性插值(
lerp)或 easing 运算 - 避免在节流内直接操作 DOM,改用 CSS
transform+will-change提升渲染性能


















