滚动事件必须节流,因其每秒触发60次以上,直接执行dom操作会导致卡顿掉帧;节流通过时间戳版(首次立即执行)或定时器版(延迟执行)控制执行频率,建议间隔从100ms起步并注意内存泄漏与同步重排问题。

滚动事件本身触发非常频繁——浏览器每秒可能触发 60 次甚至更多,直接在 scroll 回调里做 DOM 查询、计算位置或发起请求,会立刻拖慢主线程,造成卡顿、掉帧。节流就是让这个回调“减速”,控制它每固定时间最多执行一次,既保留响应性,又大幅降低开销。
为什么滚动事件必须节流
未加节流的滚动监听,哪怕只写一行 console.log(window.scrollY),在快速滚动时也会每秒打印几十上百次。真实场景中若叠加懒加载判断、吸顶逻辑、视差计算等,CPU 和渲染压力会指数级上升。节流不是“省着点用”,而是把不可控的高频信号,变成可调度、可预测的节奏。
两种主流实现方式及选择依据
节流函数通常有两种底层策略,适用不同交互需求:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 时间戳版(leading edge):记录上一次执行时间,当前时间减去它 ≥ 间隔才执行。特点是首次触发立即响应,适合需要“即时反馈”的场景,比如滚动时实时更新导航高亮。
-
定时器版(trailing edge):用
setTimeout延迟执行,并在新触发时清除旧定时器,确保间隔结束后至少执行一次。更平滑,适合滚动到底部加载数据这类“收尾动作”。
实际应用中的关键细节
光套个节流函数还不够,要注意几个易错点:
- 节流间隔不宜过小——设成
16ms(≈60fps)看似合理,但实际滚动中仍可能密集触发,建议从100ms起步,再根据体验微调; - 监听器要绑定到
window或具体容器,且记得在组件卸载或页面离开时移除,避免内存泄漏; - 如果节流后仍感觉延迟明显,检查是否在回调里做了同步重排操作(如反复读取
offsetTop),应缓存值或改用getBoundingClientRect(); - Lodash 的
_.throttle默认是 trailing 行为,加{ leading: true }可开启首帧立即执行,按需选用。
一个轻量可靠的原生节流示例
不依赖库,几行代码就能落地:
const throttle = (fn, delay) => {let last = 0;
return (...args) => {
const now = Date.now();
if (now - last >= delay) {
fn(...args);
last = now;
}
};
};
const handleScroll = () => {
// 判断是否接近底部、更新状态等
};
window.addEventListener('scroll', throttle(handleScroll, 100));
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










