应使用 intersectionobserver 实现 dom 懒加载,因其不手动监听 scroll 事件、性能更好、天然节流且避免布局抖动;三步为:标记懒加载元素、创建带阈值的观察器、在回调中加载并取消观察。

在视口滚动时结合 IntersectionObserver 实现 DOM 懒加载,核心是**不手动监听 scroll 事件**,而是用原生观察器自动触发加载逻辑——它性能更好、更精准、且天然支持节流。
为什么不用 scroll 事件做懒加载?
直接监听 window.addEventListener('scroll', ...) 容易造成高频回调、布局抖动(layout thrashing),尤其在移动端或低性能设备上卡顿明显。而 IntersectionObserver 是浏览器原生异步回调机制,只在元素真正进入/离开视口时触发,不强制重排重绘,也不需要自己写节流逻辑。
基础懒加载 DOM 的三步写法
以图片或动态插入的模块为例:
-
1. 给待懒加载的 DOM 标记一个统一 class 或 data 属性,比如:
<div class="lazy-load"></div> -
2. 创建 IntersectionObserver 实例,设置阈值(threshold)和根容器(root):
建议 threshold 设为[0, 0.1](0% 开始触发,10% 进入即加载),root 通常用null(即视口) -
3. 在回调中判断 isIntersecting,然后加载内容并取消观察:
加载后调用observer.unobserve(el)避免重复触发;若加载失败,可保留观察或加重试逻辑
实际代码示例(加载 HTML 片段)
假设页面有多个 .lazy-module 占位容器:
const lazyModules = document.querySelectorAll('.lazy-module');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const url = el.dataset.src;
if (!url) return;
fetch(url)
.then(res => res.text())
.then(html => {
el.innerHTML = html;
el.classList.remove('lazy-module'); // 可选:标记已加载
})
.catch(err => console.warn('懒加载失败:', url, err))
.finally(() => observer.unobserve(el));
}
});
}, {
threshold: [0, 0.1],
root: null // 视口为根
});
lazyModules.forEach(el => observer.observe(el));
进阶注意点
- 兼容性处理:IE 完全不支持,需用 polyfill(如 w3c 官方 polyfill)或降级为 scroll + getBoundingClientRect 判断
-
避免“闪动”或空白期:可在 CSS 中给占位元素设最小高度(
min-height: 200px)或骨架屏样式 -
动态新增的 DOM 也要观察:如果后续通过 JS 插入新懒加载节点,记得再次调用
observer.observe(newEl) -
配合 loading="lazy" 更省心:对
<img>和<iframe></iframe>,现代浏览器原生支持loading="lazy",无需 JS —— 但自定义 DOM 加载仍需 IntersectionObserver
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











