IntersectionObserver 监听元素是否出现或离开可视区域, 实现图片懒加载
IntersectionObserver 这个 API,它是异步的,不会卡主线程,相比以前监听滚动事件计算可视区域的元素,更优秀,但是不兼容 IE,好在官方提供了 polyfill 来解决这个问题。详细地址:
https://github.com/w3c/IntersectionObserver/blob/main/polyfill/intersection-observer.js
// 下面是一个手机端vue项目的应用
// 用来懒加载图片,列表一次拉20条数据,但是数据中有大图片,
// 一次加载20张大图片很慢,所以把<li>中img设置成隐藏,
// 然后循环的时候,通过序号curTargetIndex来添加class,把隐藏的图片样式设置成block(这步其实可以不写,直接用v-if判断img是否出现)
// 实现图片懒加载,光是显示隐藏还不够,这个只是影响浏览器渲染
// 必须用用v-if判断是否插入img标签, 条件和通过序号curTargetIndex来添加class是一样的
// <img v-if="v-if="(index <= (activeIndex + 3) && index >= (activeIndex - 2))"" />
// vue 的 methods 方法
lazyLoadImg() {
let _this = this
function query(selector) {
return Array.from(document.querySelectorAll(selector));
}
let allEntries = []
var observer = new IntersectionObserver(
function(entries) {
// console.log('container entries ------', entries)
// 第一次初始化,还没滚动页面的时候,会把observe监听的全部打印出来
if (entries.length > 1) {
entries.forEach((item) => {
allEntries.push(item.target)
})
}
if (entries[0].intersectionRatio <= 0) return;
if (entries.length === 1) {
// 获取出现在视窗里面的<li>的序号,通过这个序号,
// 可以设置后面5个即将出现的 li.img-block img{ display:block }
_this.curTargetIndex = allEntries.indexOf(entries[0].target)
console.log('Loaded new items', entries, _this.curTargetIndex);
}
},
{
// 如果这里不设置0.01触发事件(出现在视窗里),
// 目标div出现在视窗后,打印的intersectionRatio 全是0
threshold: [0.01],
// 这个是滚动区域的id
root: document.querySelector('#list1')
}
);
query('.pcitem').forEach(function (item, i) {
observer.observe(item);
});
}