IntersectionObserver
他提供了异步检测目标元素与祖先元素或 viewport 相交情况变化的方法
mdn
Can I use 浏览器支持情况
该方法可以实现多种效果
- 图片懒加载
- 内容区无限滚动
- …
// 他接收两个属性
let options = {
root: document.querySelector('#scrollArea'), // 指定的检测元素的父级元素,默认为未浏览器视口
rootMargin: '0px', // 跟元素的外边距
threshold: 1.0 // 检测元素与根元素的重合面积占比(0-1)
// 1--是检测元素完全在父级元素内
}
const callback=(entries, observer) => {
// entries是个数组 其中每个entry 中有isIntersecting(Boolean)属性
// 表示与视口是否重合 可以通过该属性来判断检测元素是否与父级元素重合
entries.forEach(entry => {
if(entry.isIntersecting){
// 各种操作
}
});
};
let observer = new IntersectionObserver(callback, options);
observer.observer(要检测的元素)
html结构
使用li显示文字内容模拟图片懒加载过程
<div class="box">
<li data-text="这是第1个li元素">1</li>
<!-- 使用下方快捷方式生成50个li -->
<!-- li[data-text=这是第$个li元素]*50{$} -->
</div>
实现图片懒加载:
- 通过判断滚动条的滚动距离来实现图片懒加载
不足之处是当滚动页面后才会出发事件,首次进入页面是不会出发事件
需要手动设置首屏显示内容
const lis = document.querySelectorAll("li");
const lazyLoad = () => {
lis.forEach((item) => {
// 触发条件为img元素的CSSOM对象到视口顶部的距离 < 100px + 视口高度,+100px为了提前触发图片加载
if (
item.getBoundingClientRect().top <
document.documentElement.clientHeight + 100
) {
if ("text" in item.dataset) {
ent.target.innerText='加载中....'
setTimeout(() => {
ent.target.innerText = ent.target.dataset.text;
}, 2000);
}
}
});
};
document.addEventListener("scroll", lazyLoad);
- 使用IntersectionObserver对象控制懒加载
const observer = new IntersectionObserver((entries, observer) => {
entries.map(ent => {
if (ent.isIntersecting) {
changeText(ent)
}
})
}, {
// root: document.getElementsByClassName('box')[0],
threshold: 0.8
})
const changeText = (ent) => {
ent.target.innerText='加载中....'
setTimeout(() => {
ent.target.innerText = ent.target.dataset.text;
}, 2000);
}
for (const it of document.getElementsByTagName('li')) {
observer.observe(it)
}