滚动条节流加载核心是合理控制请求时机,推荐IntersectionObserver(精准监听视口)或手动节流+滚动位置判断(兼容旧浏览器),需防重复请求、处理空数据和动态高度变化。

滚动条节流加载(也叫“懒加载”或“滚动加载”)的核心不是单纯防抖或节流,而是在滚动过程中合理控制请求时机,避免频繁触发、重复请求、错失临界点。JavaScript 中最实用的方式是结合 IntersectionObserver(推荐)或手动节流 + 滚动位置判断,下面分两种主流方案讲清楚怎么做、为什么这么选、关键细节在哪。
用 IntersectionObserver 实现更可靠、更轻量的加载
IntersectionObserver 是浏览器原生 API,能精准监听元素是否进入视口,不依赖 scroll 事件,性能好、兼容性已覆盖 Chrome 51+/Firefox 55+/Safari 12.1+。适合监听“加载占位符”(如底部 loading 元素)是否可见:
- 创建一个
<div id="loading-trigger"></div>放在列表末尾,作为触发加载的锚点 - 初始化 observer,监听该元素,一旦进入视口就加载下一页,并立即
unobserve防止重复触发 - 加载中状态要标记(如
isLoading = true),加载完成后再重新observe,避免快速滚动多次触发
示例关键逻辑:
const loadingEl = document.getElementById('loading-trigger');
let isLoading = false;
let page = 1;
<p>const observer = new IntersectionObserver(
(entries) => {
if (!entries[0].isIntersecting || isLoading) return;</p><pre class='brush:php;toolbar:false;'>isLoading = true;
loadMoreData(page++).finally(() => {
isLoading = false;
// 加载完再观察,避免连续触发
observer.observe(loadingEl);
});}, { threshold: 0.1 } // 元素 10% 进入视口即触发 );
observer.observe(loadingEl);
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
手动节流滚动事件(兼容老浏览器或特殊场景)
若需支持 IE 或需要精确控制滚动距离(比如距底部 200px 触发),可用 scroll 事件 + 节流函数。但注意:不能直接对 scroll 事件做 throttle 后查 scrollTop,否则可能漏掉最后一次临界滚动。
- 推荐使用「节流 + 最后一次检查」策略:节流间隔内只记录是否接近底部,滚动停止后立刻检查一次
- 计算是否触底:用
scrollTop + clientHeight >= scrollHeight - tolerance(tolerance 通常 100~200px) - 用
setTimeout+clearTimeout实现简易节流,比 Lodash 的 throttle 更轻、更可控
简版节流实现:
let scrollTimer = null;
const tolerance = 150;
<p>function handleScroll() {
if (isLoading) return;</p><p>const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
const nearBottom = scrollTop + clientHeight >= scrollHeight - tolerance;</p><p>if (nearBottom) {
isLoading = true;
loadMoreData(page++).finally(() => isLoading = false);
}
}</p><p>window.addEventListener('scroll', () => {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(handleScroll, 100); // 100ms 内最多执行一次
});必须处理的边界问题
不管用哪种方式,以下三点不处理就会出 bug:
-
重复请求防护:加
isLoading标志位,请求开始设为true,结束才设回false;同时禁用按钮/占位符交互 -
空数据或最后一页处理:后端返回
hasNext: false或数据为空时,应停止监听(observer.unobserve或移除 scroll 监听),并可显示“没有更多了” -
动态内容高度变化:例如图片异步加载导致页面变长,
IntersectionObserver会自动响应;但手动方案需在图片加载完成后主动触发一次检查(如监听img.onload后调用handleScroll())
不推荐的做法
直接对 scroll 事件用 debounce(防抖)——它会延迟到滚动完全停止才检查,用户快速拉到底部再松手,可能等几百毫秒才加载,体验卡顿;throttle 若没配合临界判断,容易在非底部时误触发。真正的滚动加载,关键是响应及时 + 条件精准 + 状态可控,不是单纯压事件频率。

















