目录
懒加载的来源
事件监听
IntersectionObserver
懒加载的来源
图片的来加载其实就是延迟加载,我们知道浏览器的可视范围是有限的,现在网页的内容越来越丰富,一般网页的内容都是需要滚动才能完成浏览
如果网页有很多图片,然而图片是非常吃流量的,如果用户还没看到网页下面的内容,在某种程度上我们就没必要这么快加载这些看不见的图片,懒加载的概念便由此而生。既然要滚动到网页下面才能预览到看不见的图片,我们提出以下两种方法。
事件监听
监听scroll这个事件,当鼠标滚动就会触发监听器,执行回调函数!
那么这里我们需要知道两个高度,首先是窗口显示区的高度,可以用window.innerHeight获取;其次是图片到视窗顶部的距离(高度),可以用元素的getBoundingClientRect().top来获取
图片还未被看见:图片距离视窗顶部的距离>窗口显示区的高度
图片可以被看见:图片距离视窗顶部的距离<窗口显示区的高度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片懒加载</title>
</head>
<body>
<div style="height: 110%;background-color:grey;"></div>
<!-- data-*自定义属性,浏览器碰到这个属性的时候是不会像默认属性那样进行属性处理的 -->
<div class="test"><img data-src="1.jpg"></div>
<div class="test"><img data-src="2.jpg"></div>
<div class="test"><img data-src="3.jpg"></div>
<div style="height: 30%;background-color:black;"></div>
</body>
<script>
const images = document.querySelectorAll('img')
window.addEventListener('scroll', (e) => {
images.forEach(image => {
const imageTop = image.getBoundingClientRect().top;
if (imageTop < window.innerHeight) {
const data_src = image.getAttribute('data-src');
image.setAttribute('src', data_src);
}
})
console.log('scroll触发')
})
</script>
<style>
* {
margin: 0px;
}
html,
body {
height: 100%;
}
.test {
height: 30%;
}
img {
height: 100%;
}
</style>
</html>
这里我们在网络中禁用缓存,并且用快速3G来测试恶劣的网络环境
视频演示
在视频中我们可以看见滚动事件被触发了相当多次,如果是执行一些简单的动作还好,但是页面需要加载很多内容的时候,就会导致任务的堆积,而且即使图片已经加载了还是会不断的触发事件,非常消耗资源。
IntersectionObserver
IntersectionObserver,是浏览器提供的构造函数,也就是我们可以直接拿来用,当然前提是浏览器能支持,部分浏览器版本是不兼容的
IntersectionObserver,字面意思是交叉观察,也就是目标元素和可视窗口会产生交叉区域,观察交叉区域发生了什么事情,然后我们需要执行什么程序。
构造函数接收两个参数,这里我们介绍第一个参数,第一个参数是一个回调函数,既然是回调函数一般是需要触发条件然后来执行的,这个函数一般触发两次,目标元素能看见触发一次,目标元素看不见了又触发一次
开始执行代码的时候isIntersection的值为false,也就是表示还没有进入可视区域,还没有滚动的时候是false,但是当我们滚动到图片区域,图片在可视区域的时候,isIntersection属性变为了true,有这个属性我们就可以判断该次触发回调函数时,是否已经观察到了图片。
const images = document.querySelectorAll('img')
const callback = (entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const image = entry.target;
const data_src = image.getAttribute('data-src');
image.setAttribute('src', data_src);
observer.unobserve(image)
console.log('触发')
}
})
};
const observer = new IntersectionObserver(callback)
images.forEach(image => {
observer.observe(image);
})
视频演示