何为懒加载
懒加载意在‘懒’字,即页面渲染时先用指定占位图代替,并不把页面内的所有图片都加载出来。而是‘按需’加载,当图片出现在可视区域,或者距离可视区域一定像素时才加载
其有何用
前面已介绍到,懒加载使得图片出现在可视区域时才加载。相较于一次性全部加载,最大的作用就是减少服务器压力,减少带宽。(在远古时代,img标签还会阻塞页面渲染,现代浏览器已经将img标签加载改为异步)
如何实现
前面提到,所有图片先用占位图加载,当图片出现在可视区域的时候再加载图片真实地址
这里就涉及到了两个点:
- 元素是否处于可视区域判断
- 元素属性更换
先把html代码写一下,html并无特殊之处。用data-src来存放图片真实地址,等到时候的时机再把真实地址渲染上去。至于lazyload和lazyname这两个属性,稍后会介绍
<img class="" src="/img/default.png" :data-src="item.img" lazyload="0" lazyname="lazyname" alt=""/>
现在把逻辑代码写一下
function lazyload(lazyname, viewDistance) {
const seeHeight = document.documentElement.clientHeight; // 窗口高度
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 已经滑动的高度
document.querySelectorAll('img').forEach(el => {
if (el.attributes['data-src'] && el.src !== el.attributes['data-src'].nodeValue) {
if (el.offsetTop < seeHeight + scrollTop) {
var img = document.createElement('img');
const src = el.src;
img.src = el.attributes['data-src'].nodeValue;
img.onload = e => {
el.src = el.attributes['data-src'].nodeValue;
};
img.onerror = e => {
el.attributes['data-src'].nodeValue = src;
};
}
}
});
}
以上就是一个简易且粗暴的懒加载组件,但细细想想,有没有能改进的地方呢?还记不记得html标签里有两个没有用到的属性呢,稍做修改出个 V2版本
function lazyload(lazyname, viewDistance) {
const seeHeight = document.documentElement.clientHeight; // 窗口高度
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 已经滑动的高度
let d = viewDistance || 100; // 元素距离可视区域的加载距离
let n = lazyname;
let select = document.querySelectorAll("img[lazyload='0'][lazyname=" + n + ']');
for (let i = 0; i < select.length; i++) {
if (select[i].offsetTop < seeHeight + scrollTop + d) {
if (select[i].attributes['data-src'] && select[i].src !== select[i].attributes['data-src'].nodeValue) {
var img = document.createElement('img');
const src = select[i].src;
img.src = select[i].attributes['data-src'].nodeValue;
img.onload = e => {
select[i].src = select[i].attributes['data-src'].nodeValue;
select[i].setAttribute('lazyload', 1);
};
img.onerror = e => {
select[i].attributes['data-src'].nodeValue = src;
};
}
} else {
return;
}
}
}
拎几条改造后的语句出来
let select = document.querySelectorAll("img[lazyload='0'][lazyname=" + n + ']');
// 通过lazyload属性将img标签选择器做了一次筛选,从而减少选中节点的长度,提高遍历的速度
// 而lazyname则是对img标签做精准筛选,即按需对img标签进行懒加载
img.onload = e => {
select[i].src = select[i].attributes['data-src'].nodeValue;
select[i].setAttribute('lazyload', 1);
};
// 这里将加载完成的img标签 lazyload属性值替换成1 以配合上面的选择器规则使用
至此,一个简易的懒加载器就完成了。当然,还存在很多可优化点,比如防抖等,不过这些就暂时不展开
笔者也将该懒加载器投入生产环境中,就目前来讲,没遇到什么问题。如读者朋友在使用或阅读过程有什么建议,欢迎留言,笔者看到一定及时回复