节流在滚动监听中必须用闭包维持状态,因滚动事件高频触发易致卡顿,闭包可私有持久化lasttime或timer,实现隔离、复用、防覆盖与内存泄漏。

节流在滚动监控中能真正起效,关键在于用闭包把状态“锁住”——不是简单加个 setTimeout 就完事,而是让每次调用都共享且私有地维护 lastTime 或 timer 这类变量,既不干扰其他组件,也不被外部篡改。
为什么滚动监听必须靠闭包维持状态
滚动事件每秒可能触发几十次,如果不用闭包,只能把 timer 或 lastTime 放到全局或 this 上。这样多个滚动监听器会互相覆盖,卸载组件后定时器还挂着,甚至引发内存泄漏。闭包让每个 throttle 实例拥有独立作用域,timer 和 lastTime 只属于它自己,天然隔离。
时间戳版:适合需要“稳定节奏”的滚动反馈
比如监听滚动位置判断是否接近底部、实时计算视口内元素可见性。这类场景要求函数在滚动过程中就按固定间隔执行(如每 16ms 或 100ms 一次),不能等停了才响应。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 首次触发立刻执行,之后只在间隔达标时再执行
- 不依赖定时器,无 clearTimeout 开销,性能更轻量
- 代码里 lastTime 初始为 0,每次调用比对 now - lastTime ≥ delay
定时器版:适合“松手才干活”的加载逻辑
比如滚动到底部自动加载下一页,用户还在快速滑动时没必要反复检查,等他停下来再统一处理更合理。
- 每次触发都清除前一个定时器,重设新延时任务
- 最终只执行最后一次触发后的回调,避免中间冗余判断
- 务必在回调执行后手动清空 timer = null,否则下次调用无法进入 if 分支
增强版:支持 leading / trailing 的真实业务需求
实际项目常需要“第一次立即执行 + 最后一次也执行”,比如既要立刻更新顶部状态栏(leading),又要确保滚动结束时补全数据(trailing)。这必须靠闭包统一管理三个状态:lastTime、timer、和一个标记是否已触发过 trailing 的 flag。
- leading 为 true 时,首次调用直接执行并记录时间
- trailing 为 true 时,在定时器回调里判断是否该补一次(即本次调用后没再触发)
- 所有状态都在闭包内初始化,不会跨实例污染










