最新最简单最直观实现图片懒加载
Intersection Observer
在实现这个功能之前,我们首先来认识一下IntersectionObserver函数,在MDN中,是这样描述的:提供了一种异步观察元素与其祖先元素或顶级文档视图(Viewport)交叉状态的方法。祖先元素与视窗(Viewport) 被称为根(root)。
当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦IntersectionObserver被创建,则无法更改其配置,所以一个给定的观察者对象只能用监听区域的特定变化值;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.root {
width: 500px;
height: 600px;
border: 1px solid #000;
overflow: scroll;
}
.root .container {
width: 100%;
height: 300px;
border: 1px solid green;
margin-bottom: 30px;
}
.root .container img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div class="root">
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201906/zzpic18628.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201907/bpic12621.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201907/bpic12546.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201905/zzpic18002.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201905/hpic999.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201905/bpic11868.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201904/zzpic17739.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201904/bpic11187.jpg" alt="">
</div>
<div class="container">
<img src="" data-src="http://pics.sc.chinaz.com/files/pic/pic9/201903/bpic10945.jpg" alt="">
</div>
</div>
<script>
let options = {
root: document.querySelector('.root') //用于观察的根元素,默认是浏览器的视口
}
let io = new IntersectionObserver(call, options) // 参数一:监听函数 参数二:监听父级对象
function call(e) {
e.forEach(item => {
// false:不在视窗,true:在视窗中
if(item.isIntersecting) { //当前元素在视窗里
item.target.src = item.target.dataset.src // 替换src
io.unobserve(item.target) //取消监听,防止重复调用
}
})
}
let imgs = document.querySelectorAll('.container img')
imgs.forEach(item => {
io.observe(item) // 开启监听所有元素
})
</script>
</body>
</html>