图片懒加载的简单实现

为什么要使用懒加载

在网页中,我们有时候需要展示多张图片。如果图片太多,页面的加载速度会慢很多,这样会非常影响用户体验。所以,在图片过多的页面,为了加速页面的加载进度,我们需要将页面中没出现在可视区域内的图片先不做加载,等图片滚动到可视区域内时,再把图片加载出来,这样对于页面的加载性能会有很大的提升。

懒加载的原理

将页面中所有img标签的src统一设置为一张占位图进行占位,然后给每个img标签添加一个属性data-src(这个属性可以自定义)指向图片的真实地址。

当载入页面时,先把可视区域内的img标签的data-src属性值赋给src属性。然后监听滚动事件,当img标签出现在可视区域时,把data-src属性值赋给src属性。

这样,便实现了懒加载。

懒加载的实现

直接上代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
<img src="frngji01(3).png" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
</body>

上面为html部分,是一些图片。

接下来,我们给img标签加一些样式。

1
2
3
4
5
6
img {
display: block;
margin-bottom: 50px;
width: 400px;
height: 400px;
}

现在,页面中就有一些一列排的占位图片。

接下来,就来实现懒加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function lazyload(){
let n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历
return function () {
let num = document.getElementsByTagName('img').length,//获取图片的个数
img = document.getElementsByTagName("img"),
seeHeight = document.documentElement.clientHeight || document.body.clientHeight, //可见区域高度
scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //滚动条距离顶部高度
for (let i = n; i < num; i++) {
//判断图片是否进入可视区域
if (img[i].offsetTop < seeHeight + scrollTop) {
if (img[i].getAttribute("src") == "frngji01(3).png") {
img[i].src = img[i].getAttribute("data-src");
}
n = i + 1;
}
}
}
}

这样,我们就实现了懒加载的基本逻辑。
接下来我们需要在页面刚开始加载时,就把可视区域的图片加载出来。

1
2
let lazyInit = lazyload();
lazyInit();//页面载入完毕加载可试区域内的图片

然后,我们监听页面的滚动事件。

1
window.addEventListener('scroll', lazyInit);

但到这里,我们的懒加载是不完善的。
js中的函数节流(throttle)和函数去抖(debounce)中说过,当需要监听scroll事件时,我们一般会使用throttle节流方法。

接下来,我们就来完善一下我们的代码。

首先,先定义一个节流的函数。

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
function throttle(func, wait) {
// 为了避免每次调用lastTime都被清空,利用闭包返回一个function确保不声明全局变量也可以
let lastTime = null
let timeout
return function () {
let context = this;
let now = new Date();
let arg = arguments;
// 如果上次执行的时间和这次触发的时间大于一个执行周期,则执行
if (now - lastTime - wait > 0) {
// 如果之前有了定时任务则清除
if (timeout) {
clearTimeout(timeout)
timeout = null
}
func.apply(context, arg)
lastTime = now
} else if (!timeout) {
timeout = setTimeout(() => {
// 改变执行上下文环境
func.apply(context, arg)
}, wait)
}
}
}

然后,再调用节流的方法

1
let lazyScroll = throttle(lazyInit, 800);

最后,我们修改scroll事件的回调方法为lazyScroll。

1
window.addEventListener('scroll', lazyScroll);

到这里,我们就实现了一个简单的懒加载。

如有错误,欢迎指正!

参考资料

前端如何实现图片懒加载(lazyload) 提高用户体验

--本文结束感谢您的阅读--