lazyLoad-懒加载

懒加载也叫延迟加载,指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式。用户滚动到它们之前,可视区域外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些情况下,它还可以帮助减少服务器负载。

适用场景:商城网站或者图片很多的其他展示性网站中。

那使用懒加载的优点有哪些呢?

  • 能提升用户的体验。
  • 减少无效资源的加载,减小服务器和浏览器的负担。
  • 防止并发加载的资源过多而导致阻塞JS的加载。
原理

那么我们会经常把src的属性设置为空字符串,或者一个其他的静态图片,而图片的真实路径则设置在自定义属性中去,比如 data-src。然后监听页面的滚动事件,在滚动事件的回调函数中,判断我们的懒加载的图片是否进入可视区域。如果进入到可视区域,就把src的值设置为 data-src的值,从而实现懒加载的效果。

示例代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>lazy</title>
	<style type="text/css">
		img {
			display: block;
			width: 104px;
			height: 144px;
		}
	</style>
</head>
<body>
	<div class="lazyObj">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
		<img src="" data-src="https://user-gold-cdn.xitu.io/2017/12/13/1604f3080efffc24?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1">
	</div>
</body>
</html>
<script type="text/javascript">
	
	// 获取可视区域的高度
	var viewHeight = document.documentElement.clientHeight;

	function lazy() {
		// 获取所有的Img标签
		var lazyImg = document.getElementsByTagName('img');

		// 这里打印出来的lazyImg是一个obj,所以不能直接使用 forEach 方法
		// console.log(typeof lazyImg)

		// 循环数组,将Array的forEach方法用到 lazyImg 上去
		// 简写 [].forEach.call(...)
		Array.prototype.forEach.call(lazyImg, function(item, index) {
			// 定义一个变量来用作判断是否进到可视区域的范围
			let rect;
			if (item.dataset.src === "" || item.dataset.src === undefined) return;

			// 用于获得页面中某个元素的左,上,右,下分别相对于浏览器视窗的位置
			rect = item.getBoundingClientRect();

			// 判断图片位置是否进入到了可视区域
			if (rect.bottom >= 0 && rect.top < viewHeight) {
				item.src = item.dataset.src;
				item.removeAttribute("data-src");
			}
 		})
	}

	// 这里也需要给scroll事件放一个函数节流来减少性能损耗
	function throttle (fn, time) {
		let flag = true;
		return function () {
			if (!flag) return;
			flag = false;
			setTimeout(() => {
				fn.apply(this, arguments);
				flag = true;
			}, time)
		}
	}

	lazy();
	window.addEventListener('scroll', throttle(lazy, 300));
</script>
封装版本
  1. 在上述代码块基础上进行封装–有优化空间

使用此方法,会在调用时,多次获取DOM节点,尤其是在 scroll 这种高频触发的事件中,会消耗浏览器性能,且在使用节流时,得再包裹一层中间层,否则无法传递参数

优化建议:

如果是固定的元素节点,可以把获取DOM部分也设为一个常量;但如果是动态加载,则还是需要动态去获取DOM节点。

// 获取可视区域的高度
var viewHeight = document.documentElement.clientHeight;
function lazy(selector, type) {
	// 获取所有的Img标签
	var lazyImg = document.querySelectorAll(selector);

	// 这里打印出来的lazyImg是一个obj,所以不能直接使用 forEach 方法
	// console.log(typeof lazyImg)

	// 循环数组,将Array的forEach方法用到 lazyImg 上去
	Array.prototype.forEach.call(lazyImg, function(item, index) {
		// 定义一个变量来用作判断是否进到可视区域的范围
		let rect;
		if (item.dataset.src === "" || item.dataset.src === undefined) return;

		// 用于获得页面中某个元素的左,上,右,下分别相对于浏览器视窗的位置
		rect = item.getBoundingClientRect();

		// 判断图片位置是否进入到了可视区域
		if (rect.bottom >= 0 && rect.top < viewHeight) {
			item.src = item.dataset.src;
			item.removeAttribute(type);
		}
 	})
}

// 这里也需要给scroll事件放一个函数节流来减少性能损耗
function throttle (fn, time) {
	let flag = true;
	return function () {
		if (!flag) return;
		flag = false;
		setTimeout(() => {
			fn.apply(this, arguments);
			flag = true;
		}, time)
	}
}

// 使用此种传参方式,得再包一层
lazy('img[data-src]', 'data-src');

// 中间层
function lazyLoad () {
	lazy('img[data-src]', 'data-src');
}

window.addEventListener('scroll', throttle(lazyLoad, 300));

// 测试耗时 43.331298828125ms
  1. 使用类和单例模式进行封装

此方法,将高度,选择器,加载属性都定义在了构造方法里,并且使用单例模式,确保只初始化一个实例,之后的 onscroll 事件里,只需要调用 init 方法即可。

可优化的点:

将循环后已经加载出来的的元素节点删除掉,可提高下次循环效率

class Lazy {
	constructor (selector, type) {
		this.selector = selector;
		this.type = type;
		// 获取可视区域的高度
		this.viewHeight = document.documentElement.clientHeight;
		// 获取所有的Img标签
		this.lazyImg = document.querySelectorAll(this.selector);
		this.init();
	}
	init () {
		// this 作用域
		let _this = this;
		// 循环数组,将Array的forEach方法用到 lazyImg 上去
		Array.prototype.forEach.call(_this.lazyImg, function(item, index) {
			// 定义一个变量来用作判断是否进到可视区域的范围
			let rect;
			if (item.dataset.src === "" || item.dataset.src === undefined) return;

			// 用于获得页面中某个元素的左,上,右,下分别相对于浏览器视窗的位置
			rect = item.getBoundingClientRect();

			// 判断图片位置是否进入到了可视区域
			if (rect.bottom >= 0 && rect.top < _this.viewHeight) {
				item.src = item.dataset.src;
				item.removeAttribute(_this.type);
			}
 		})
	}
}

// 使用单例模式
Lazy.getSelector = (function(){
	let instance;
	return function (selector, type) {
		if (!instance) {
			instance = new Lazy(selector, type);
		}
		return instance;
	}
})()

// 这里也需要给scroll事件放一个函数节流来减少性能损耗
function throttle (obj, fn, time) {
	let flag = true;
	return function () {
		if (!flag) return;
		flag = false;
		setTimeout(() => {
			// fn();
			fn.apply(obj, arguments);
			// 这里不能使用this,它会将作用域指向当前触发事件的对象上去
			// fn.apply(this, arguments);
			flag = true;
		}, time)
	}
}



let lazy = Lazy.getSelector('img[data-src]', 'data-src');
window.addEventListener('scroll', throttle(lazy, lazy.init, 300));

公众号:Coder 杂谈,欢迎关注
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值