htmledit_views">
方案 1:使用
方案 2:使用
方案 3:使用
懒加载,顾名思义,在当前网页,滑动页面到能看到图片的时候再加载图片
故问题拆分成两个:
- 如何判断图片出现在了当前视口 (即如何判断我们能够看到图片)
- 如何控制图片的加载
方案 1:使用 IntersectionObserver
(推荐)
IntersectionObserver
是现代浏览器提供的 API,可高效监听元素是否进入视口。
实现步骤
- 给
img
添加data-src
存储真实图片 URL,初始src
设为空或占位图。 - 使用
IntersectionObserver
监听图片是否进入视口。 - 进入视口时,将
data-src
赋值给src
,触发图片加载。
代码示例
html"><img class="lazy" data-src="real-image.jpg" src="placeholder.jpg" alt="Lazy Image">
document.addEventListener("DOMContentLoaded", function () {
let lazyImages = document.querySelectorAll("img.lazy");
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
let img = entry.target;
img.src = img.dataset.src;
img.classList.remove("lazy"); // 移除类,避免重复加载
observer.unobserve(img); // 取消观察,减少性能消耗
}
});
}, {
root: null, // 视口
threshold: 0.1 // 触发懒加载的阈值
});
lazyImages.forEach(img => observer.observe(img));
});
优点:
- 高效:浏览器 API 提供回调,仅在图片进入视口时触发。
- 可控:可自定义触发阈值
threshold
(例如0.1
表示 10% 进入视口时加载)。
方案 2:使用 getBoundingClientRect() + scroll 事件
(兼容旧浏览器)
如果需要支持不兼容 IntersectionObserver
的旧版浏览器,可以使用 getBoundingClientRect()
结合 scroll
事件手动监听。
实现步骤
- 监听
scroll
事件,遍历所有lazy
图片。 - 使用
getBoundingClientRect()
判断图片是否进入视口。 - 进入视口后加载图片并移除监听。
代码示例
function lazyLoad() {
let lazyImages = document.querySelectorAll("img.lazy");
let windowHeight = window.innerHeight;
lazyImages.forEach(img => {
let rect = img.getBoundingClientRect();
if (rect.top < windowHeight && rect.bottom > 0) { // 判断是否在视口内
img.src = img.dataset.src;
img.classList.remove("lazy");
}
});
if (document.querySelectorAll("img.lazy").length === 0) {
window.removeEventListener("scroll", lazyLoad); // 所有图片加载完后移除事件监听
}
}
document.addEventListener("DOMContentLoaded", () => {
window.addEventListener("scroll", lazyLoad);
lazyLoad(); // 初次执行,确保首屏图片加载
});
缺点:
- 性能问题:
scroll
事件会频繁触发,需要使用 防抖(debounce
)优化。 - 兼容性好:适用于旧版浏览器。
方案 3:使用 loading="lazy"
(最简单,浏览器原生支持)
HTML5 提供 loading="lazy"
属性,浏览器会自动判断图片是否需要懒加载。
html"><img src="real-image.jpg" loading="lazy" alt="Lazy Image">
优点:
- 最简单,无需 JS,浏览器自动处理懒加载。
- 兼容性一般,现代浏览器(Chrome 76+,Firefox 75+,Edge 79+)支持。
缺点:
- 无法自定义触发时机,受浏览器策略控制。
- 不支持旧版浏览器,如 Safari 15 之前。
最佳方案推荐:
- 现代浏览器:使用
IntersectionObserver
(推荐)- 兼容性要求高:
scroll + getBoundingClientRect()
- 简单项目:直接用
loading="lazy"
(最方便)