实现懒加载的四种方式
# 第一种
图片距离浏览器视口顶部距离 <= 浏览器视口高度 + 页面滚动距离
const imgs = document.getElementsByTagName('img');
function lazyLoad(imgs) {
console.log('触发了');
// 视口的高度;
const clientH = document.documentElement.clientHeight;
// 滚动的距离,这里的逻辑判断是为了做兼容性处理;
const clientT = document.documentElement.scrollTop || document.body.scrollTop;
for(let i = 0; i < imgs.length; i++) {
// 逻辑判断,如果视口高度+滚动距离 > 图片到浏览器顶部的距离就去加载;
// !imgs[i].src 是避免重复请求,可以把该条件取消试试:可以看到不加该条件的话往回滚动就会重复请求;
if(clientH + clientT > imgs[i].offsetTop && !imgs[i].src) {
// 使用data-xx的自定义属性可以通过dom元素的dataset.xx取得;
imgs[i].src = imgs[i].dataset.src;
}
}
};
// 一开始能够加载显示在视口中的图片;
lazyLoad(imgs);
// 设置节流函数
function throttle(fn, delay) {
let timer = null;
return () => {
if(timer) {
return;
};
timer = setTimeout(() => {
fn(imgs);
timer = null;
}, delay)
}
}
// 监听滚动事件,加载后面的图片;
window.onscroll = throttle(lazyLoad, 500);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 第二种
Element.getBoundingClientRect()
方法返回元素的大小及其相对于视口的位置。我们可以取得它的top
值,它的top
值就是元素左上角到视口顶部的距离。当Element.getBoundingClientRect().top < 视口高度
时触发加载;
const imgs = document.getElementsByTagName('img');
// 判断元素是否出现在视口内
function isShow(el) {
// 视口高度
const clientH = window.innerHeight;
const bound = el.getBoundingClientRect();
// 判断元素左上角到视口顶部的距离是否小于视口高度
return bound.top < clientH;
};
// 加载图片
function showImg(el) {
if(!el.src) {
el.src = el.dataset.src;
}
}
// 懒加载
function lazyLoad() {
console.log('加载了');
[...imgs].forEach(el => {
if(isShow(el)) {
showImg(el);
}
})
};
lazyLoad();
// 节流函数
function throttle(fn, delay) {
let timer = null;
return () => {
if(timer) {
return;
};
timer = setTimeout(() => {
fn(imgs);
timer = null;
}, delay);
}
};
window.onscroll = throttle(lazyLoad, 500);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 第三种
IntersectionObserver
可以异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。也就是说它可以帮助我们去判断一个元素是否出现在视口上。这里只介绍用到的两个属性:
IntersectionObserver.observe()
:使IntersectionObserver开始监听一个目标元素;
isIntersecting
属性:可以判断该元素是否出现在视口内;
实现思路:根据上面介绍的那两个属性,我们可以遍历每个img元素,然后监听每一个元素,最后根据isIntersecting属性去判断元素是否出现在视口内,从而决定是否让它加载。
document.addEventListener("DOMContentLoaded", () => {
if ("IntersectionObserver" in window) {
const imgs = document.getElementsByTagName("img");
const imageObserve = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
// 通过该属性判断元素是否出现在视口内
if (entry.isIntersecting) {
// entry.target能够取得那个dom元素
const data_src = ele.target.getAttribute('data-src'); //这里基本和 Method1/Method2一样
ele.target.setAttribute('src', data_src); // ele.target 是目标元素
// 解除监视
imageObserve.unobserve(img);
}
});
});
[...imgs].forEach((img) => {
// 开启监视每一个元素
imageObserve.observe(img);
});
} else {
alert("您的浏览器不支持IntersectionObserver!");
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 第四种
img
标签原生支持loading属性,可取值有:- eager:无论图片是否在可视区,都会直接加载图片
- lazy:推迟图片的加载,当图片滚动到距离可视区域一定阈值(视浏览器的实现而定)的时候,再加载图片
- auto:由浏览器自行决定
最近更新时间: 2021/08/25 17:25:09
- 01
- 2023/07/03 00:00:00
- 02
- 2023/04/22 00:00:00
- 03
- 2023/02/16 00:00:00