作为网页内容的一部分,图像和视频通常要消耗很多资源加载。要提高网页应用的性能,如何避免资源浪费在加载图像和视频上就很重要了。但是,很多时候我们都不愿意减少网页上的媒体资源,所以我们经常无从下手。幸运的是,我们有懒加载这个绝招,它可以帮助我们减少加载时间和降低负载,而不在内容上偷工减料。

1.懒加载工作原理

通俗点讲,就是在页面还没到达图片位置的时候不用事先加载,不作显示或者设置loading加载。只有当页面滚动条到达图片所在位置,才将真正的图片渲染到页面上去。显然,这里需要通过监听scroll滚动事件实现懒加载效果。

2.懒加载实现方案

通过分析,我们需要知道两个高度:窗口显示区的高度和图片到视窗上边的距离高度。
图片未能看见:图片距离视窗顶部的距离 > 窗口显示区的高度。
图片能看见:图片距离视窗顶部的距离 < 窗口显示区的高度。

首先,可以给图片设置一个自定义属性data-src,默认src属性则设置为loading加载图片或者为空。其中 data- 为自定义属性,通常情况下,浏览器不会执行自定义属性。之后,添加滚动监听事件,将img的自定义属性data-src赋值给默认属性src。


3.核心js代码

注意:使用offsetTop和scrollTop的时候一定要保证当前页面元素已全部被渲染。

// 获取所有img的dom元素   并全部设置为loading加载图片
let imgs = document.querySelectorAll('img');
imgs.forEach(img => {
	img.src = './loading.gif';
})
// 懒加载函数
const lazyload = () => {
	imgs.forEach(img => {
		//图片距离顶部的距离   包含卷上去的部分
		let imgoffsettop = img.offsetTop;
		// 页面被卷去的高度
		let scrollT = document.documentElement.scrollTop;
		//浏览器可视区的高度
		let view = window.innerHeight;
		// 图片到视窗上边的距离高度 < 窗口显示区的高度 ,这时候,才需要加载
		if (imgoffsettop - scrollT < view) {
			//设置一个定时器  目的是为了让懒加载的效果更明显
			setTimeout(() => {
				img.src = img.dataset.src
			}, 800);
		}
	})
}
// onload保证页面元素已全部渲染 
window.onload = function() {
	//进入页面 初始化执行
	lazyload();
	//滚动执行
	window.addEventListener('scroll', lazyload);
}


4.html代码

示例代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<img
			data-src="https://img0.baidu.com/it/u=128726096,3499341032&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=698"></img>
		<img
			data-src="https://img1.baidu.com/it/u=2944608286,2060518702&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=727"></img>
		<div></div>
		<img
			data-src="https://img2.baidu.com/it/u=3274749659,1709808198&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750"></img>
		<img
			data-src="https://img2.baidu.com/it/u=2357389186,1982056366&fm=253&fmt=auto&app=120&f=JPEG?w=640&h=960"></img>
		<div></div>
		<img
			data-src="https://img2.baidu.com/it/u=3711757854,2517951413&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=700"></img>
		<img
			data-src="https://img2.baidu.com/it/u=3532455937,1503056366&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=1422"></img>
		<div></div>
		<img data-src="https://img2.baidu.com/it/u=4192422414,1862812180&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750">
		<img data-src="https://img1.baidu.com/it/u=4069446031,1929672719&fm=253&fmt=auto&app=138&f=JPEG?w=333&h=500">
		<div></div>
		<img data-src="https://img1.baidu.com/it/u=1846905306,2792027856&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=779">
		<img data-src="https://img0.baidu.com/it/u=1993836752,2372618051&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889">
		<div></div>
		<img data-src="https://img1.baidu.com/it/u=4216615779,3871708882&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889">
		<img data-src="https://img2.baidu.com/it/u=109659060,2014363234&fm=253&fmt=auto&app=138&f=JPEG?w=334&h=500">
		<div></div>
		<img data-src="https://img2.baidu.com/it/u=2991838151,1877228912&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=888">
		<img data-src="https://img0.baidu.com/it/u=642326292,3709733592&fm=253&fmt=auto&app=138&f=JPEG?w=346&h=500">
		<style>
			img {
				height: 300px;
				width: 230px;
			}
                        /* div的目的仅仅是为了撑开图片之间的上下距离  更好的模拟业务场景 */
			div {
				height: 200px;
			}
		</style>
	</body>
</html>