节流函数在窗口事件中核心作用是控制回调执行频次,避免高频触发导致的性能浪费,实现在滚动或缩放过程中有节奏、保底式执行,兼顾响应性与效率。

节流函数在窗口监听事件(如 resize、scroll)中,核心作用是控制回调执行频次,避免因事件高频触发导致的性能浪费——比如重复计算尺寸、频繁重排重绘、无谓的 DOM 操作或状态更新。它不是“等停了再执行”,而是在滚动或缩放过程中,**有节奏地、保底式地执行**,兼顾响应性与效率。
为什么窗口事件必须加节流
浏览器对 resize 和 scroll 的触发极其密集:一次快速拖拽窗口可能触发几十次 resize;滚动页面时,scroll 在 1 秒内可触发上百次。若每次触发都执行获取宽高、判断位置、setState 或请求数据等操作,CPU 占用飙升,页面易卡顿甚至假死。
- resize 事件:窗口边缘被拖动时连续触发,未节流时每像素变化都可能调用回调
- scroll 事件:尤其在长列表、瀑布流或吸顶导航场景下,不节流会导致监听逻辑反复执行,影响主线程
- 现代浏览器还会对未声明
passive: true的scroll监听器强制同步阻塞滚动,节流不能替代这个底层优化,但二者需配合使用
节流参数怎么设才合理
常见误区是盲目设 100ms 或 300ms。实际应结合用途和设备刷新率权衡:
- 用于 UI 布局适配(如响应式栅格重算)、数据懒加载:推荐 16–60ms 区间,接近
requestAnimationFrame帧率(约 60fps),视觉更顺滑 - 用于防抖式节流(如只关心最终尺寸):可用 200–500ms,兼顾用户操作完成感与执行及时性
- 移动端触摸滚动更敏感,建议下限不低于 32ms,避免过度抑制
- 不要设低于 10ms——既无感知提升,又增加调度开销
React 中正确集成节流 resize 监听
关键点不在“有没有节流”,而在“节流是否稳定、是否干净卸载、是否不破坏 React 更新机制”:
- 节流函数必须在组件外定义或用
useCallback缓存,否则每次渲染都会新建闭包,导致removeEventListener失效 - 不要把
setState直接传入节流函数——应封装为稳定引用的处理函数,避免闭包捕获过期 state - 务必在
useEffect清理函数中移除监听,防止内存泄漏和卸载后更新报错 - 示例中
throttle(handleResize, 300)返回的是新函数,需确保该函数在整个生命周期内唯一
比节流更关键的底层优化
节流只是上层策略,真正影响滚动流畅度的还有两个常被忽略的硬性配置:
-
scroll 监听必须加
{ passive: true }:告诉浏览器“我不会调用preventDefault()”,允许异步处理,避免强制同步阻塞。不加它,节流效果大打折扣 -
优先考虑
requestAnimationFrame节流:它天然对齐屏幕刷新节奏,比定时器更精准、更节能。适合需要平滑反馈的场景(如视差滚动、吸顶状态更新) - 对纯“到达临界点”判断(如滚动到底部),可结合
IntersectionObserver替代 scroll 监听,完全脱离事件循环压力

















