图片懒加载是一种优化网页性能的技术,它可以延迟加载图片,直到图片进入浏览器的可视区域,从而减少初始加载时的资源消耗,提升页面加载速度。
- 加载时机 :
data-src
本身不会触发资源的加载,它只是一个数据存储的地方。只有当通过 JavaScript 等方式将data-src
的值赋给src
属性时,浏览器才会发起对该资源的请求。 src
是标准的 HTML 属性,用于指定资源的来源地址,浏览器会立即加载该资源。data-src
是自定义属性,用于存储自定义数据。
IntersectionObserver
IntersectionObserver
是浏览器提供的一个用于异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的 API。它在处理懒加载、无限滚动、广告曝光监测等场景中非常有用,下面从几个方面详细介绍它。
基本原理
IntersectionObserver
允许你注册一个回调函数,当目标元素与指定的根元素(默认为浏览器视口)的交集区域发生变化时,这个回调函数会被触发。它采用了一种非阻塞的异步方式,避免了传统通过监听 scroll
、resize
等事件进行元素可见性检测时可能带来的性能问题。
基本用法
使用 IntersectionObserver
主要有以下几个步骤:
1. 创建 IntersectionObserver
实例
javascript
ini
const observer = new IntersectionObserver(callback, options);
-
callback
:当目标元素的可见性发生变化时会调用的回调函数,该函数接收两个参数:entries
:一个包含所有被观察元素的IntersectionObserverEntry
对象的数组,每个IntersectionObserverEntry
对象描述了一个被观察元素的可见性变化信息。observer
:当前的IntersectionObserver
实例。
-
options
:一个可选的配置对象,包含以下属性:root
:指定根元素,即用于检查目标元素可见性的元素,默认为浏览器视口。rootMargin
:根元素的外边距,类似于 CSS 的margin
属性,用于扩展或缩小根元素的边界框,格式为"10px 20px 30px 40px"
。threshold
:一个数值或数值数组,定义了一个或多个交叉比例阈值,当目标元素与根元素的交叉比例达到这些阈值时,回调函数会被触发。例如,[0, 0.5, 1]
表示当目标元素的可见比例为 0%、50%、100% 时都会触发回调。
2. 观察目标元素
ini
const target = document.getElementById('target-element');
observer.observe(target);
通过 observe
方法可以让 IntersectionObserver
开始观察指定的目标元素。
3. 停止观察目标元素
ini
observer.unobserve(target);
使用 unobserve
方法可以停止对某个目标元素的观察。
原生 JavaScript 实现
通过监听窗口滚动事件和 IntersectionObserver
API 来实现图片懒加载。
-
HTML 部分 :为需要懒加载的图片添加
lazyload
类,并将真实的图片地址存储在data-src
属性中,src
属性设置为一个占位图片(这里使用了一个透明的 GIF 图片)。 -
JavaScript 部分:
- IntersectionObserver :如果浏览器支持
IntersectionObserver
,则使用它来监听图片是否进入可视区域。当图片进入可视区域时,将data-src
的值赋给src
属性,并停止观察该图片。 - 降级处理 :如果浏览器不支持
IntersectionObserver
,则监听scroll
、resize
和orientationChange
事件,在事件触发时检查图片是否进入可视区域
- IntersectionObserver :如果浏览器支持
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IntersectionObserver 图片懒加载示例</title>
</head>
<body>
<img class="lazy" data-src="https://picsum.photos/200/300" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Lazy Loaded Image">
<img class="lazy" data-src="https://picsum.photos/200/300?random=2" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Lazy Loaded Image">
<script>
const lazyImages = document.querySelectorAll('img.lazy');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});
lazyImages.forEach((image) => {
observer.observe(image);
});
</script>
</body>
</html>
代码解释
- 首先,获取所有带有
lazy
类的图片元素。 - 然后,创建一个
IntersectionObserver
实例,当目标元素进入视口(isIntersecting
为true
)时,将data-src
属性的值赋给src
属性,移除lazy
类,并停止对该元素的观察。 - 最后,对每个图片元素调用
observe
方法,开始观察它们的可见性变化。
兼容性
IntersectionObserver
已经得到了大多数现代浏览器的支持,但在一些旧版本的浏览器中可能不支持。在使用时,可以结合一些兼容性处理,例如使用 IntersectionObserver
进行懒加载,同时为不支持的浏览器提供降级方案(如监听 scroll
事件)。