原理
将img标签src
属性指向一张默认图片,然后定义data-src
属性指向真实的图片。
图片要指定宽高
<img class="lazy-img" src="./imgs/lazy.png" data-src="./imgs/fact.png" alt/>
当载入页面时,监听页面滚动事件:当滚动到图片的可视区(或者还有某段固定距离)时,把图片的img标签的data-src属性值赋给src属性,从而发起请求将图片加载显示。
代码
在写代码前,需要了解各种高度。可参考这篇文章:scrollTop等元素距离
const lazyload = {
data: {
imgs: [], // 懒加载图片集
startIndex: 0, // 懒加载开始位置
visibleHeight: document.documentElement.clientHeight + 50, // 可见区域高度 + 提前加载距离
scrollTop: 0, //滚动条距离顶部高度
loadHeight: 0,
during: 100, // 节流时间
startTime: Date.now(),
listener: null, // 滚动监听器
timer: null // 节流监听器
},
// 图片懒加载
lazyload() {
this.data.scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
this.data.loadHeight = this.data.visibleHeight + this.data.scrollTop;
console.log('滚动监听中...');
//监听页面滚动事件
for (let i = this.data.startIndex; i < this.data.imgs.length; i++) {
console.log('查询中...' + this.data.imgs[i].scrollTop + ' , ' + this.data.loadHeight);
if (this.data.imgs[i].offsetTop > this.data.loadHeight) {
break;
}
this.data.imgs[i].src = this.data.imgs[i].getAttribute('data-src');
console.log(this.data.imgs[i], '完成懒加载' + i);
this.data.startIndex = i + 1;
if (this.data.startIndex === this.data.imgs.length) {
console.log('图片全部加载完毕,移除滚动监听');
// 图片全部加载完毕,移除滚动监听
window.removeEventListener('scroll', this.data.listener);
}
}
},
// 缓存中读取图片
cacheload() {
for (var i = 0; i < this.data.imgs.length; i++) {
this.data.imgs[i].src = this.data.imgs[i].getAttribute('data-src');
}
},
// 节流
throttle() {
return () => {
clearTimeout(this.data.timer);
let now = Date.now();
if (now > this.data.startTime + this.data.during) {
this.lazyload();
this.data.startTime = now;
} else {
this.data.timer = setTimeout(() => {
this.lazyload();
}, this.data.during);
}
};
},
// 初始化函数
init() {
this.data.imgs = document.querySelectorAll('.lazy-img');
if (JSON.parse(sessionStorage.getItem('loaded'))) {
// 二次加载,无需执行懒加载
this.cacheload();
} else {
// 首次加载,需执行懒加载
sessionStorage.setItem('loaded', true);
this.lazyload();
window.addEventListener('scroll', (this.data.listener = this.throttle.call(this)));
}
}
};
lazyload.init();
思考
- 第一次进入页面时图片使用懒加载,再次进入不发触发懒加载
优化: 使用session判断是否是首次加载页面,是否需要执行懒加载
- 如果直接将函数绑定在scroll事件上,当页面滚动时,函数会被高频触发,这非常影响浏览器的性能
使用函数节流来限制触发频率,优化性能 探究JS系列(二)节流与防抖
- 页面加载完成后,不等用户滚动页面。主动去请求懒加载图片资源。