前言:图片懒加载是一种对网页性能优化的方式,当访问一个页面的时候,优先加载可视区域的图片,而不是一次性把页面中的图片都请求加载出来。通过这种方式可以使页面加载速度变快,减轻服务器的压力,节省流量。

  • 简单来说:就是不一次性加载那么多图片,而是慢慢来,按需加载。
  • 比较建议的方法是通过 IntesectionObserve 这个API来实现

实现原理

  1. 首先获取当前元素距离顶部的距离
  2. 再获取屏幕的高度

主要方法:

1
2
1DOMobj.getBoundingClientRect().top   //获取该元素到屏幕顶部的距离
2window.innerHeight //屏幕的高度

简易版懒加载

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
45
46
47
48
49
50
51
<body>
<div class="box">
<img data-src="image1.jpg" class="lazy-load"
src="loading.gif" alt="1" srcset="">
<img data-src="image2.jpg" class="lazy-load"
src="loading.gif" alt="2" srcset="">
<img data-src="image3.jpg" class="lazy-load"
src="loading.gif" alt="3" srcset="">
<img data-src="image4.jpg" class="lazy-load"
src="loading.gif" alt="4" srcset="">
<img data-src="image5.jpg" class="lazy-load"
src="loading.gif" alt="5" srcset="">
<img data-src="image6.jpg" class="lazy-load"
src="loading.gif" alt="6" srcset="">
<img data-src="image7.jpg" class="lazy-load"
src="loading.gif" alt="7" srcset="">
</div>
</body>

<style>
.box{
width: 50%;
margin: 0 auto;
}

.box img{
width: 100%;
height: 100%;
}

</style>

<script>

function imgLazyLoad(){
// 把类数组转换为真数组
var imgs = [...document.querySelectorAll('.lazy-load')]
imgs.forEach(img => {
if(img.getBoundingClientRect().top < window.innerHeight){
// 图片一旦有src就会加载出来,所以图片的路径不会放在src中,而是一个自定义的属性data-src中
img.src = img.dataset.src
}
});
}

// 页面第一次加载,触发事件,屏幕内的图片正常加载,屏幕外的用scr内的代替
window.onload = imgLazyLoad;
// 监听滚轮事件
window.addEventListener('scroll',imgLazyLoad)

</script>

效果

  • 效果图被干掉了。。。。。晚点找个时间补上

优化

监听鼠标滚轮过于频繁,应该进行节流优化一下

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
<script>
function imgLazyLoad(){
// 把类数组转换为真数组
var imgs = [...document.querySelectorAll('.lazy-load')]
imgs.forEach(img => {
if(img.getBoundingClientRect().top < window.innerHeight){
// 图片一旦有src就会加载出来,所以图片的路径不会放在src中,而是一个自定义的属性data-src中
img.src = img.dataset.src
}
});
}

// 页面第一次加载,触发事件,屏幕内的图片正常加载,屏幕外的用scr内的代替
window.onload = imgLazyLoad;
// 监听滚轮事件
var listenScroll = true
// 设置节流让其300ms只执行一次这个函数
window.addEventListener('scroll',() =>{
//在设定的时间内,则不执行函数
if(!listenScroll){
return ;
}else{
// 定时器事件
setTimeout(() =>{
imgLazyLoad()
// 事件执行完成之后,将监听事件的变量listenScroll变为true,即监听过了
listenScroll = true
},300);
// 定时器执行完之后,再重新赋值监听事件的变量listenScroll
listenScroll = false
}
})
</script>

再优化(最好的方法)

  • 上面这种方式虽然也实现了懒加载,但是还是有一点缺点,就是一当发生滚动事件时,就发生了大量的循环和判断操作判断图片是否可视区里。
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
const images = document.querySelectorAll('.lazy-load');

// 回调函数
function lazyLoad(entries, observer) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target; // 获取图片
img.src = img.dataset.src; // 加载图像
observer.unobserve(img); // 停止监听已加载的图像
}
});
}

// 选项
const options = {
root: null,
rootMargin: '0px',
threshold: 0.1
};

const observer = new IntersectionObserver(lazyLoad, options);

// 观察每个图像元素
images.forEach(img => {
observer.observe(img);
});