先看
效果
。
➖ 上效果
第一个效果:
图片懒加载
这些图片一开始
是一个默认
图片。当你滑过去
的时候,它会加载
出真实
的图片。
第二个效果:
加载更多
在瀑布流布局中,会加载一个小圈圈在转。当滑过去的时候,更多
内容会被加载
。
第三个效果:
广告播放
这个广告在这里播放,但当你滑下去时,它会暂停。用户必须完整
看到广告后,才能继续播放
。
➖ 咋做
🔹 前期唠嗑
监听滚动条
以前咱做这玩意,可能第一反应就是监听
这个滚动条
。
看元素滚动的位置去判断。
缺点
:
1、滚动事件不断触发
,影响效率。
2、计算
一些滚动位置,相对麻烦
些。
现在咱有这个Intersection Observer
,吃点好的,方便简洁相对好用,看看有些需求咱能不能用上吧。
官方文档
🔹 切入做法
🔶 第一个效果 图片懒加载
🔻 创建观察
写页面:
html
<div class="card-list">
<div class="item">
<img src="./default.png" alt="" data-src="https://picsum.photos/400/600?r=1" />
</div>
<div class="item">
<img src="./default.png" alt="" data-src="https://picsum.photos/400/600?r=1" />
</div>
// ... 省略的代码 要100个item
</div>
创建观察器
js
const ob = new IntersectionObserver();
进行观察
js
const ob = new IntersectionObserver();
ob.ovserve(xxx) // xxx代表被观察的dom元素。
这里xxx
的dom就是我们要观察的,带有data-src
图片的元素。
js
const ob = new IntersectionObserver();
// 拿到图片dom,带有data-src的image
const imgs = document.querySelectorAll('img[data-src]');
// 然后呢,去循环这个图片,循环图片去观察每一个图片。
// 这个观察器,它是可以观察很多元素的,它可以不只观察一个元素。
imgs.forEach(img => {
ob.observe(img);
})
// ob.observe(xxx)
观察了图了,达到条件后,叫它做什么这个回调函数也要告诉这个观察器。
js
// 回调函数
const ob = new IntersectionObserver(() => {
console.log('交叉了,运行这个回调函数。')
});
const imgs = document.querySelectorAll('img[data-src]');
// 循环图片去观察每一个图片。
imgs.forEach(img => {
ob.observe(img);
})
再加配置
。
三
个参
。
js
const ob = new IntersectionObserver(() => {
console.log('交叉了,运行这个回调函数。')
}, {
root: null,
rootMargin: '0px 0px 0px 0px',
threshould: 0
});
🔻 细说配置
root
:
就是观察
的这个元素,跟谁
在交叉
。
默认
值就是null
。
默认
的话就不用写
。
rootMargin
:
边距。
看它要交叉
的那个元素的边距
。
正数:比如10px
,就是差10px
要交叉了,就算交叉。
负数:比如-10px
,就是交叉了还不行,要超过10px
才去运行回调函数。
默认是'0px 0px 0px 0px'
。默认可不写。
threshould
:
观察的阈值。
范围是0到1
。
默认是0
。
两次回调
。
头尾碰到阈值就调回调
。
0
是只要碰上。
1
是完全离开。
🔻 回调参数
回调参数这里说的是entries
。
它是个数组,实际就是把所有在被观察的元素以数组的形式告诉我们。
js
// 回调函数
const ob = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log('交叉了')
}
}
}, {
threshould: 0
});
const imgs = document.querySelectorAll('img[data-src]');
imgs.forEach(img => {
ob.observe(img);
})
entries
里面是一个个对象,每个对象是一个INtersectionObserverEntry
。
isIntersecting
(布尔值)交叉了就true
,否则false
。
交叉之后呢,就把data-src
的值给到src
就可以了。
js
// 回调函数
const ob = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // 把data-src里的值,设置给img的src。
ob.unobserve(img); // 通过这个函数去取消观察。以后就不需要观察它了。
}
}
}, {
threshould: 0
});
const imgs = document.querySelectorAll('img[data-src]');
imgs.forEach(img => {
ob.observe(img);
})
// ob.unobserve(img);
// 做了之后就不做了,通过这个函数去取消观察
。以后就不需要观察它
了。
🔶 第二个效果 加载更多
js
async function loadMoreImages (number = 10) {
isLoading = false;
}
loadMoreImages(30);
const ob = new IntersectionObserver((entries) => {
// 这里只观察它的第一个元素。
const entry = entries[0]
// 如果它已经有交叉了,那我们就去加载更多的10张图
if (entry.isIntersecting) {
loadMoreImages(10); // 就完事了。
}
}, {
threshold: 0,
});
// 那么它跟视口有交叉的情况下,就是能看见的情况下,给它设置一个阈值。
ob.observe(document.querySelector('.load-more'));
🔶 第三个效果 广告不全就停
js
const vd = document.querySelector('video');
const ob = new IntersectionObserver((entries) => {
const entry = entries[0]
if (entry.isIntersecting) {
vd.play();
} else {
vd.pause();
}
}, {
threshold: 1 // 必须完整看到这个广告, 我才给你播放
});
ob.observe(vd);
threshold: 1
:
只要这个视频被遮住
了一点点,都给它停
了,
要完整
看到这个视频广告,才给你播
。
threshold: 0.6
:
如果这样子太变态太没人性,
就可以调一下这个threshold这个值。
不要设为1,
可以设为0.6
这样。
这样子呢,
一开始可以看到这个视频,
到这个视频的60%
被遮盖之后,就给它暂停。不超过60%就给它播
。
➖ 大白话小结
IntersectionObserver 提供了一种高效
的方式来处理元素
与视口
的交互
,
避免了繁琐的滚动事件监控
,
使得性能优化变得简单
而直观
。
☎️ 希望对大家有所帮助,本文有些地方可能考虑不够周到,有些纰漏,就当抛砖引玉,还望您海涵,如有错误,望不吝赐教,欢迎评论区留言互相学习。感谢阅读,祝您开发有乐趣。