跳到主内容

图片懒加载的最好实现方案,Intersection Observer使用教程

· 6分钟阅读

图片懒加载作为前端性能优化的一个关键环节,可以提高页面加载速度,减少页面白屏时间,提高用户体验。在之前的做法可能通过监听页面滚动事件,判断元素的是否在可视区域,然后再加载图片。然而这种做法并不是最好的,幸运的是,浏览器提供了一个原生的 API,叫做 Intersection Observer,它可以异步检测目标元素与祖先元素或者浏览器的视图窗口相交 🍌 的情况,当条件满足,就会触发回调函数。我们就可以在这个回调函数里面做文章。

浏览器的视图窗口:在浏览器范畴里,它代表的是浏览器中网站可见内容的部分。视口外的内容在被滚动进来前都是不可见的。

intersection

如何实现

Intersection Observer API 的定义

IntersectionObserver(callback, options);

第一个参数是执行的回调,我们主要看第二个参数 optionsoptions 可以配置字段有:

root: 指定目标元素的父元素,如果不指定,则默认为视图窗口。

rootMargin: 指定目标元素的父元素的 margin 距离,如果不指定,则默认为 0px。

rootMargin

threshold:指定目标元素与祖先元素的相交比例,如果不指定,则默认为 0。值可以是数字或者数组,小数表示百分比,比如可见区域超过 30% 才触发,则配置 0.3。如果配置数组,则表示每隔一个范围就触发一次,比如每隔 1/3 触发一次,则配置 [0, 0.33, 0.66, 1]。

实战

接下来我们来实现一个图片懒加载功能,我们新建一个 html 结果如下

<style>
html,
body {
height: 100%;
}
.container {
height: 2000px;
}
.content {
height: 1200px;
background-color: #f0f0f0;
}
img {
width: 400px;
height: 400px;
object-fit: cover;
}
</style>
<div class="container">
<img data-src="https://tvax4.sinaimg.cn/large/006z7Mergy1gysjqfzyopj30go0b4n4e.jpg" />
<div class="content"></div>
<img data-src="https://tvax4.sinaimg.cn/large/006z7Mergy1gysjqfzyopj30go0b4n4e.jpg" />
</div>

我们设置 container 元素高度大于可视区域,这样可以在浏览器出现滚动条,然后在 content 区域的上方和下方各放置一个图片,但是图片不直接设置 src 属性,而是配置 data-src ,这个值就是图片的真实地址。

我们接下来实现的功能是,当首次打开页面,第一个图片直接加载,但第二个图片不加载,只有当滚动到第二个图片出现在可视区域时,才加载。于是我们编写下面的脚本

const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.dataset.src;
img.src = src;
observer.unobserve(img);
}
});
},
{
rootMargin: "0px",
threshold: 0,
}
);
const imgs = document.querySelectorAll("img");
[...imgs].forEach((img) => {
observer.observe(img);
});

直接浏览器运行,可以得出,浏览器会先加载第一个图片,第二张图片不默认加载,当滚动出现后才会加载。完美~ 😄

实时 DEMO

Live Editor
Result
Loading...

交集计算规则

如果元素是不规则的图形也将会被看成一个包含元素所有区域的最小矩形,如果元素发生的交集部分不是一个矩形,那么也会被看作是一个包含他所有交集区域的最小矩形。

其他用途

Intersection Observer 除了图片懒加载,还有其他用途,比如:

  • 滚动到底部加载数据,当底部 loading 元素出现在视图交叉区域时,就可以触发加载数据
  • 控制视频在可视区域才播放,避免无效播放
  • 广告展示检测,统计广告的展示次数
  • 更多的用途。。。