前言
功能参考饿了么的图片组件里的懒加载图片(地址)
想要实现在快滚动到底部的时候去动态加载图片,前面写到过的监听滚动条去做懒加载也可以做到,但是想用更优雅的写法来实现,即用本地占位图片来替换网络图片,当视图加载到占位图片的视图的时候,将占位图片替换成网络图片。
这样做的好处是当你开发一个图片量比较多的项目的时候,不必等所有的图片都加载完成了才能友好访问,可以直接加载当前可视区域里的图片,其他区域的内容可以等滚动到当前视图之前加载。这样可以提高网站的友好体验,不必等那个几秒加载完成。
那么,怎么能做到监听懒加载的视图到达可视区域呢?
已经有原生支持监听可是区域的功能了,它就是IntersectionObserver
IntersectionObserver
mdn
先查看兼容情况
目前绝大多数浏览器都支持的差不多了,除了ie(毕竟巨硬都放弃了)那就没必要考虑了吧!
上面的mdn里有介绍intersectionObserver有两个形参,一个是回调函数,第二个是可选的配置项;
-
回调函数
回调函数有两个形参,第一个是entries, entries是一个数组,每个成员都是一个IntersectionObserverEntry对象
如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员;第二个参数是当前被调用的IntersectionObserver实例 -
配置项
root 详见mdn
rootMargin 详见mdn
threshold 重点说下threshold,它是一个具体的数值或者是一个数值的数组,值为0-1之间。0 代表视图即将加载到可视区域之前,而1则是视图(视图的高度)完完全全加载到可视区域了。没有修改配置的话 默认该项都是0,即马上就到可视区域了去触发回调。
实例
<div class="banner"></div>
<div class="content"></div>
<div class="img">
<span>loading</span>
</div>
<style>
div, body, html {
padding: 0;
margin: 0;
}
.banner {
width: 100%;
height: 100vh;
background-color: aqua;
}
.content {
height: 200px;
background-color: aquamarine;
}
.img {
min-height: 300px;
background-color: aliceblue;
text-align: center;
}
.img>span {
line-height: 300px;
font-size: 50px;
}
</style>
<script>
const img = document.querySelector('.img');
const observer = new IntersectionObserver((e, self) => {
console.log(e)
const status = e.some(item => item.intersectionRatio > 0);
if (status) {
createImgEle();
if (e.some(el => el.target === img)) self.unobserve(img)
}
}, {
threshold: 0
})
observer.observe(img);
function createImgEle() {
const imgctx = document.createElement('img');
const loading = document.querySelector('.img>span');
imgctx.src = 'https://img2.baidu.com/it/u=4084621093,2971972319&fm=253&fmt=auto&app=120&f=JPEG?w=889&h=500';
img.append(imgctx);
img.removeChild(loading)
}
</script>
这里以懒加载一张图片为例,当加载到div.img时会执行callback回调 去生成一个新的img元素(其实一开始是打算不创建img 只替换img.src的,但没有找到那张Loading图片,就手动创建了个img来替换。。。)
更高级的用法比如注册成vue的自定义指令(感谢春神提供的素材)