当一个页面需要展示很多图片的时候, 如果不使用懒加载技术, 一次性加载成百上千的图片的时候, 可能会出现下面的图片加载完了, 但是可视区域的图片却还在加载中, 造成极其不好的体验. 因为浏览器对一个域名的请求数量是有限制的, chrom是一次最多加载6张图片, 超过这个数量, 其他图片就会进入请求队列. 只有前面的加载完, 后面的才能继续加载.
节流
为什么要了解节流的思想? 因为图片懒加载是在鼠标滚轮滚动的时候触发, 如果不加限制, 那么当用户滚动比较快的时候, 一次性加载图片也是巨量的, 会导致懒加载看不出效果来.
节流就是在n秒内触发的同一个事件会被忽略掉, 只会在停下触发n秒后才会执行
鼠标滚轮触发是非常频繁的, 可能滚动一次可能会触发几十上百次. 使用节流的话, 只会触发一次.
throttle(func, wait) {
// func - 滚轮事件的处理函数
// wait - 间隔秒数, 连续触发的两次事件间隔小于这个事件都会被忽略掉, 只会执行最后一次
let timeout;
let startTime = new Date();
return function(e) {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
timeout = setTimeout(func, wait);
};
}
这里实际使用的是一个闭包的思想, 在wait毫秒内触发的事件, 都会把这个一次性定时器清除掉. 并重新创建一个wait毫秒的定时器. 只有触发事件间隔大于wait秒, 才会执行func函数
懒加载思想
懒加载主要是处理鼠标滚动到指定位置的时候, 可视区域能看到想要看的图片.
比如有这么一段html代码:
<div id="lazy-load" class="img-con">
<span class="img-item">
<img src="empty.png" data-mid="1" alt="">
</span>
</div>
这里 .img-con 表示图片容器的div, .img-item是单个图片的容器 为啥要在img标签外面包一层span, 因为没包被坑过不少次, 包一层以后修改样式啥的, 会更方便点, 包一层能解决很多问题. 经验之谈.
懒加载js处理部分
document.getElementById('lazy-load').addEventListener('scroll', throttle(imgLazyLoad, 30, 300), true);
imgLazyLoad = (data=[]) => {
// data: 对象数组, {mid: '', imgSrc: '图片地址'}每个对象里面有一个图片地址属性
// 修改判断逻辑,从可见部分开始加载
// pic - 图片模式 , list - 列表模式
let imgCon = null;
// 获取图片容器的位置信息和尺寸信息
imgCon = document.querySelector('.img-con');
if (imgCon) {
const imgs = imgCon.querySelectorAll('img');
if (imgs) {
// 获取mid对应的真实图片路径
const relImgs = {};
for (let i=0; i<data.length; i++) {
const item1 = data[i];
relImgs[item1.mid] = item1.imgSrc;
}
// 获取图片的位置信息和尺寸信息
const conElInfo = imgCon.getBoundingClientRect();
for (let i=0; i<imgs.length; i++) {
const item = imgs[i];
const curMid = item.getAttribute('data-mid');
const curInfo = item.getBoundingClientRect();
// 核心处理: 判断当前图片是否在可视区域内
if ((curInfo.top+curInfo.height) - conElInfo.top > 0) {
// 校验图片地址真实存在
if (relImgs[curMid] && relImgs[curMid]!=='') {
// 当前图片如果是一张占位图, 则加载真实图片, 否则认为该图片已经加载好了
if(item.src.indexOf('empty.png')!==-1) {
item.src = relImgs[curMid];
}
}
}
}
}
}
}
这里面的核心思路就是判断当前图片是否在可视区域内 (curInfo.top+curInfo.height) - conElInfo.top > 0: curInfo.top+curInfo.height: 图片底部距离页面顶部的距离 conElInfo.top: 图片容器距离页面顶部的距离 (curInfo.top+curInfo.height) - conElInfo.top: 判断元素是否在图片容器可视区内
总结
图片懒加载技术的核心就是节流思想和位置判断, 掌握这两个思路了, 其它可以自己调整, 这里的节流我也没用完整, 把不需要的部分截取掉了, 不用多少时间内一定加载一次. 更加适合我做的项目.