为什么需要懒加载?
在一些图片比较多的网站(比如说大型电商网站)图片是非常多的,如果我们在打开网页的一瞬间就把网站的所有图片加载出来,很有可能造成卡顿和白屏的现象,用户体验变得极其的差,要是遇到脾气暴躁的小伙伴相信直接反手就是一个Ctrl+W。
因为图片真的很多,一瞬间就把网站的所有图片加载出来浏览器短时间内根本处理不完,但是我们打开网站的那一瞬间仅仅只能看到视口内的图片,这时候去加载网页最底部的图片是非常浪费资源和没有必要的,所以遇到这种情况使用懒加载
技术就显得尤为必要了。
懒加载实现原理
懒加载的原理其实很简单,就是预先将图片真实的src
放在我们自定义的属性里面(比如data-src
),当图片出现在了我们的视口范围之内的时候,再把data-src
赋值给src
属性,完成图片加载。
// 页面初始化时
<img data-src="https://img11.360buyimg.com/pop/s590x470.jpg.webp" />
// 当图片出现在了视口范围之内
<img data-src="https://img11.360buyimg.com/pop/s590x470.jpg.webp" src="https://img11.360buyimg.com/pop/s590x470.jpg.webp"/>
这里有个点就是初始化时可以不给img标签加上src
属性,因为只要存在src
属性,浏览器就会去执行一次请求将其指向的资源下载并应用到文档内,这里不加上可以提升一些性能
具体实现
基于前面讲解的思路,我们自己手写一个懒加载
新建一个lazyload.html
文件,初始化dom结构并设置对应的样式
<!DOCTYPE html>
<html>
<head>
<title>lazy load</title>
<style>
.img {
width: 220px;
height: 220px;
background-color: #ccc;
margin-bottom: 40px;
margin-left: 50px;
}
.pic {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="container">
<!--将真实的src先放在data-src中-->
<div class="img">
<img class="pic" data-src="https://img10.360buyimg.com/n7/jfs/t1/183679/11/2189/143829/6091f5d8E933e7ad1/e3e2001666f2ce7b.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img12.360buyimg.com/n7/jfs/t1/192682/11/617/163213/608b887aEddbbbee3/9570466a90d02f79.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img14.360buyimg.com/n7/jfs/t1/156161/35/18802/268242/60641d96Eca3dee7f/4a32070a19deb4f5.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img10.360buyimg.com/n7/jfs/t1/130179/12/9273/167054/5f5468edE9d4ecd9c/39f7520d9f76b695.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img14.360buyimg.com/n7/jfs/t1/100888/13/13132/105320/5e5533c6Ea8daa487/f95d7ba4da5581c5.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img10.360buyimg.com/n7/jfs/t1/173986/31/8862/291849/6098d6d0E26c55012/c2144f6e074556d2.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img10.360buyimg.com/n7/jfs/t1/110754/4/12605/101916/5ee43244E6fbf9433/c42fb5e3f9558a59.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img10.360buyimg.com/n7/jfs/t1/148370/31/1084/45848/5eedc2eeEfdc2cd46/f3c3a6f0bd7998be.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img10.360buyimg.com/n7/jfs/t1/165930/8/7273/171076/602fd5dfE65a52775/ee27074b7037c020.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img13.360buyimg.com/n7/jfs/t1/190093/28/117/193777/60867822Ea949fbec/6fe51b122d0fdc5a.jpg" />
</div>
<div class="img">
<img class="pic" data-src="https://img14.360buyimg.com/n7/jfs/t1/119501/15/6768/115886/5eca6c36Eb3541dc9/2f4534173878a23c.jpg" />
</div>
</div>
</body>
</html>
接下来是JS部分,我们需要提前知道几个值,一个是当前浏览器窗口的视口高度,另一个是每张图片距离视口顶部的距离,因为只有当图片距离顶部的距离小于我们的视口高度,那么就代表这张图片已经出现在我们的视口范围内了。
获取浏览器视口高度
获取可视区域的高度我们通常使用window.innerHeight
就可以拿到了,当然如果需要兼容低版本IE浏览器的话则可以使用document.documentElement.clientHeight
来获取,这里我们做一个兼容处理
const viewPortHeight = window.innerHeight || document.documentElement.clientHeight
获取图片离顶部的距离
这里我们简单粗暴一点,直接使用getBoundingClientRect()
这个方法来获取,对这个方法不了解的小伙伴可以点击这里进行查看
到这里,我们所需要的两个值就都可以拿到了,下面直接上代码:
// 获取所有图片
const imgList = document.querySelectorAll('img')
// 用于记录当前显示到了哪一张图片
let index = 0;
function lazyload() {
// 获取浏览器视口高度,这里写在函数内部是考虑浏览器窗口大小改变的情况
const viewPortHeight = window.innerHeight || document.documentElement.clientHeight
for (let i = index; i < imgList.length; i++) {
// 这里用可视区域高度减去图片顶部距离可视区域顶部的高度
const distance = viewPortHeight - imgList[i].getBoundingClientRect().top;
// 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明图片已经出现在了视口范围内
if (distance >= 0) {
// 给图片赋值真实的src,展示图片
imgList[i].src = imgList[i].getAttribute('data-src');
// 前i张图片已经加载完毕,下次从第i+1张开始检查是否需要显示
index = i + 1;
}
}
}
// 定义一个防抖函数
function debounce(fn, delay = 500, ...args) {
let timer = null;
// 这里的e是event事件对象
return function (e) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
// 页面加载完成执行一次lazyload,渲染第一次打开的网页视口内的图片
window.onload = lazyload;
// 监听Scroll事件,为了防止频繁调用,使用防抖函数进行优化
window.addEventListener("scroll", debounce(lazyload, 600));
// 浏览器窗口大小改变时重新计算
window.addEventListener("resize", debounce(lazyload, 600));
最后效果
到这里我们的图片懒加载就写完了,下面是效果图,喜欢的朋友麻烦点个赞吧
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!