什么叫懒加载?
懒加载是相对于预加载的一个概念。预加载是在用户查看之前加载数据,等用户查看的时候,能够很快显示。而懒加载是延时加载,就是在用户需要用到的时候再去加载,可以减少请求次数、降低内存消耗。
比如我们加载一个页面,这个页面很长很长,长到我们的浏览器可视区域装不下,那么懒加载就是优先加载可视区域的内容,其他部分等进入了可视区域在加载。
懒加载原理
一张图片就是一个<img>标签,浏览器是否发起请求图片是根据<img>的src属性,所以实现懒加载的关键就是:在图片没有进入可视区域时,先不给<img>的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。
相关API
首先介绍几个常用的API:
document.documentElement.clientHeight //获取屏幕可视区域的高度,不包括水平滚动条、边框和外边距
element.offsetTop //获取元素相对于文档顶部的高度,注意是HTML文档顶部,也就是整个页面
document.documentElement.scrollTop //获取浏览器窗口顶部与文档顶部之间的距离,也就是竖直滚动条已经滚动的距离
以下图片可以方便我们理解这三个概念:
根据这些我们可以得到一个判断公式:
如果图片进入了可视区内,相当于:offsetTop-scroolTop<clientHeight,则被请求。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>懒加载</title>
<style>
.top{
height: 800px;
width: 100%;
background-color: aqua;
}
img {
display: block;
width: 100%;
height: 722px;
}
</style>
</head>
<body>
<div class="top"></div>
<img data-src="./image1.jpg" src=""/>
<img data-src="./image2.jpg" src=""/>
<img data-src="./image3.jpg" src=""/>
<img data-src="./image4.jpg" src=""/>
<img data-src="./image5.jpg" src=""/>
<script>
function lazyLoad(imgs){
var c = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
var s = document.documentElement.scrollTop || document.body.scrollTop;
for(img of imgs){
let o = img.offsetTop;
if(o < c + s){
console.log('src', o, c, s)
img.src = img.getAttribute('data-src');
img.className='img'
}
}
}
var imgs = document.querySelectorAll('img');
window.onload = window.onscroll = function(){
lazyLoad(imgs);
}
</script>
</body>
</html>
更加简单快捷的API:getBoundingClientRect()
getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, bottom, left, right, width, height等属性。
- element.getBoundingClientRect().top:元素上边到视窗上边的距离;
- element.getBoundingClientRect().right:元素右边到视窗左边的距离;
- element.getBoundingClientRect().bottom:元素下边到视窗上边的距离;
- element.getBoundingClientRect().left:元素左边到视窗左边的距离;
- element.getBoundingClientRect().width:元素的宽度;
- element.getBoundingClientRect().height:元素的高度
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>懒加载</title>
<style>
html, body, ul{
margin: 0;
}
li{
list-style: none;
height: 200px;
}
img{
height: 200px;
}
</style>
</head>
<body>
<ul>
<li data-src="http://cover.read.duokan.com/mfsv2/download/fdsc3/p01N203pHTU7/Wr5314kcLAtVCi.jpg!t"></li>
<li data-src="http://77fkxu.com1.z0.glb.clouddn.com/20160308/1457402219_73571.jpg"></li>
<li data-src="http://cover.read.duokan.com/mfsv2/download/fdsc3/p01a3SXHo2hZ/XYAC5TLk4uYWXn.jpg!t"></li>
<li data-src="http://pic1.cxtuku.com/00/16/18/b3809a2ba0f3.jpg"></li>
<li data-src="http://cover.read.duokan.com/mfsv2/download/fdsc3/p015trgKM7vw/H0iyDPPneOVrA4.jpg!t"></li>
<li data-src="http://77fkxu.com1.z0.glb.clouddn.com/20160308/1457402219_73571.jpg"></li>
<li data-src="http://imgsrc.baidu.com/baike/pic/item/2f9cbdcc5e0bcf5c00e9283b.jpg"></li>
<li data-src="http://pic1.cxtuku.com/00/16/18/b3809a2ba0f3.jpg"></li>
<li data-src="http://cover.read.duokan.com/mfsv2/download/fdsc3/p015trgKM7vw/H0iyDPPneOVrA4.jpg!t"></li>
<li data-src="http://77fkxu.com1.z0.glb.clouddn.com/20160308/1457402219_73571.jpg"></li>
<li data-src="http://imgsrc.baidu.com/baike/pic/item/2f9cbdcc5e0bcf5c00e9283b.jpg"></li>
<li data-src="http://pic1.cxtuku.com/00/16/18/b3809a2ba0f3.jpg"></li>
</ul>
<script>
var imgs = document.querySelectorAll('li');
window.onload = window.onscroll = function(){
lazyLoad(imgs);
}
function lazyLoad(imgs){
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
for(img of imgs){
const pos = img.getBoundingClientRect();
if(pos.y>=0 && pos.y<=clientHeight && img.children.length < 1){
var image = new Image();
image.src = img.getAttribute('data-src');
img.style.display = 'inline'
img.appendChild(image);
}
}
}
</script>
</body>
</html>
【参考文献】
https://zhuanlan.zhihu.com/p/55311726