节流scroll事件能有效减少重复计算和DOM查询,避免主线程频繁中断;推荐使用带首次立即执行的手写节流函数,并叠加预加载距离、筛选未加载图片等策略优化懒加载。

直接用节流(throttle)处理 scroll 事件,能有效减少重复计算和 DOM 查询次数,避免主线程被频繁打断。关键不是“要不要节流”,而是“怎么节流才合理”——既要保证图片及时加载,又不能漏掉该触发的时机。
为什么 scroll 事件必须节流
滚动过程中,scroll 事件每秒可能触发几十甚至上百次。若每次触发都遍历所有懒加载图片并调用 getBoundingClientRect(),会造成:
- CPU 高频计算位置,影响滚动流畅性(尤其低端安卓机)
- 重复读取已加载过的图片,浪费判断逻辑
- 未加节流时,同一张图可能被多次赋值
src(虽无实质错误,但不严谨)
节流函数的推荐写法(轻量、无依赖)
不用第三方库,手写一个带“首次立即执行”的节流函数更可控:
function throttle(fn, delay) {
let last = 0;
return function (...args) {
const now = Date.now();
if (now - last > delay) {
fn.apply(this, args);
last = now;
}
};
}
<p>const checkVisible = throttle(() => {
const windowHeight = window.innerHeight;
document.querySelectorAll('img[data-src]').forEach(img => {
if (!img.src && img.getBoundingClientRect().top </p><p>window.addEventListener('scroll', checkVisible);
checkVisible(); // 页面加载后立即检查首屏
</p>
比单纯节流更有效的组合策略
节流只是基础,实际项目中建议叠加以下优化点:
-
只检查未加载的图片:用
document.querySelectorAll('img[data-src]')筛选,避免遍历已加载或无效元素 -
预加载距离(提前触发):把判断条件从
top 改为top ,让图片在进入视口前就开始加载,消除滚动过程中的白屏感 -
加载后移除监听目标:对已赋值
src的图片,可改用 class 标记(如img.classList.add('loaded')),后续查询跳过它们 -
搭配 Intersection Observer 降级使用:现代浏览器优先用
IntersectionObserver,它本身是异步且原生节流的;scroll + 节流仅作为兼容 fallback(如需支持 IE 或旧安卓 WebView)
常见误区提醒
别把节流延迟设得太长(比如 1s),否则用户快速滚动时,底部图片会明显滞后加载;也别用防抖(debounce)替代节流——防抖会在滚动停止后才执行,无法满足“边滚边加载”的需求。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











