滚动事件需节流以避免高频触发导致卡顿,通过限制固定时间只执行一次回调(如200ms),大幅降低主线程压力;手写节流函数基于时间戳判断,lodash版支持首尾执行更鲁棒。

页面滚动事件(scroll)天然高频,用户轻轻一滚,几毫秒内就可能触发十几次。如果回调里有 DOM 查询、计算位置、发请求或更新界面等操作,主线程很快被占满,导致卡顿、掉帧甚至内存压力。节流就是为这类场景设计的——它不阻止事件发生,而是控制处理函数的执行节奏,确保“固定时间只干一次”。
为什么滚动事件特别需要节流
滚动不是单次动作,而是一个持续过程。浏览器每帧都可能派发 scroll 事件,但你通常不需要每帧都响应。比如判断某个元素是否进入视口、显示/隐藏回到顶部按钮、做懒加载边界检测,这些操作本身不需实时到毫秒级,100–300ms 一次已足够平滑且省资源。
- 不做节流:一秒滚动触发 60+ 次 → 回调执行 60+ 次 → 大量
getBoundingClientRect()和重排重绘 - 加节流(如 200ms):一秒最多执行 5 次 → 主线程压力大幅下降,体验更稳
手写一个轻量节流函数
不用依赖库也能快速实现,核心是记录上一次执行时间,只在间隔达标后才运行:
function throttle(fn, delay) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}
用法示例:
const handleScroll = throttle(() => {
const scrollTop = window.scrollY;
const target = document.querySelector('.section');
if (target && scrollTop > target.offsetTop - 200) {
console.log('目标区域已接近');
}
}, 200);
<p>window.addEventListener('scroll', handleScroll);</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill7710" title="前端设计优化skill"><img
src="https://img.php.cn/upload/skill/000/000/081/179163003435961.jpg" alt="前端设计优化skill" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill7710" title="前端设计优化skill" class="overflowclass">前端设计优化skill</a>
<p class="overflowclass">前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。</p>
</div>
<a rel="nofollow" href="/xiazai/skill7710" title="前端设计优化skill" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
用 Lodash 快速接入(推荐工程中使用)
安装:npm install lodash
引入并使用:
import { throttle } from 'lodash';
<p>const handleScroll = throttle((e) => {
console.log('滚动位置:', window.scrollY);
// 执行视口检测、状态更新等
}, 250, {
leading: true, // 首次滚动立即执行(可选)
trailing: true // 最后一次滚动结束也执行(可选)
});</p><p>window.addEventListener('scroll', handleScroll);</p>
注意:Lodash 的 throttle 默认开启 leading 和 trailing,意味着滚动开始和结束各保底一次执行,比纯时间戳版更鲁棒,适合多数业务逻辑。
实际开发中的关键提醒
- 别在节流回调里频繁读写 DOM:把
document.querySelector提到外面缓存,避免每次执行都查一遍 - 避免在节流函数中直接调用
setState(React)或响应式赋值(Vue),建议用防抖或useCallback + useMemo配合优化 - 移动端要注意
touchmove也可能需要节流,逻辑类似,只是绑定事件不同 - 调试时可在控制台临时加
console.time('scroll')/console.timeEnd('scroll')看单次耗时,再对比节流前后的 FPS 变化
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










