用intersectionobserver实现懒加载和无限滚动的关键是合理配置rootmargin、threshold参数,及时unobserve元素并销毁观察器。图片加载设data-src+占位图,哨兵元素监听列表底部,配合loading锁与错误兜底确保稳定。
用 intersectionobserver 实现图片懒加载和无限滚动列表,关键不在写多少代码,而在配对参数、理清触发时机、及时释放资源。下面分两块讲清楚怎么做。
图片懒加载:让图片“快到眼前才动身”
核心是监听图片是否即将进入视口,并在合适时机加载真实地址。
-
HTML 结构要规范:图片的
src先设为占位图(如 base64 或轻量小图),真实地址存进data-src属性里。这样页面一打开不会批量请求大图。 -
rootMargin 预留加载缓冲区:设成
"200px"或"150px 0px",意思是图片距离视口顶部还有 150–200px 时就开始加载。这个值太小会卡顿,太大可能提前加载太多无用图;实测 150–250px 在多数网络和设备上比较稳。 -
threshold 控制触发灵敏度:用
0.01(即 1% 可见)即可,避免因元素刚露一点边就反复触发;不建议用数组阈值,除非做动画,否则增加计算开销。 -
加载完立刻取消观察:在回调里调用
observer.unobserve(img)。否则即使图片已加载,它还在持续被监听,浪费内存和性能。
无限滚动列表:监听“底部哨兵”代替 scroll
不再监听整个窗口滚动,而是放一个空的哨兵元素(sentinel)在列表末尾,用它来触发下一页加载。
-
DOM 中插入哨兵节点:在列表容器最底部加一个带唯一 class 或 id 的空
<div id="sentinel"></div>,不占视觉空间,仅作监听用。 -
rootMargin 向下扩展检测区域:配置
rootMargin: "200px 0px 0px 0px",让哨兵在离视口底部还有 200px 时就触发,给数据请求留出时间,避免用户“拉到底才动”。 -
加状态锁防重复请求:在回调中先判断
!isLoading,再发起请求;请求开始设isLoading = true,结束再置为false,避免快速滚动多次触发。 -
加载完成后重置哨兵位置:新数据追加后,
observer.unobserve(sentinel)再observer.observe(sentinel),确保它始终处于新列表末尾——尤其在动态更新 DOM 时这步不能省。
共用优化点:提升稳定性和可维护性
两个场景都适用的细节处理,能避免线上翻车。
-
root 设为 null 即可:默认监听浏览器视口,除非你有局部滚动容器(比如弹窗内列表),才需要指定
root: document.querySelector('.scroll-wrapper')。 -
错误兜底不能少:图片加载失败时,保留
onerror回调并 fallback 到占位图或报错占位;接口请求失败也要提示用户并允许手动重试。 -
销毁观察器要主动:组件卸载或页面跳转前,调用
observer.disconnect()。Vue/React 中放在onBeforeUnmount或useEffect cleanup里执行。











