原生js实现懒加载并节流

摘要:像淘宝网站等,页面中有着大量图片,一次性全部加载这些图片会使浏览器发送大量请求和造成浪费。采用懒加载技术,即用户浏览到哪儿,就加载该处的图片。这样节省网络资源、提升用户体验、减少服务器压力。

像淘宝网站等,页面中有着大量图片,一次性全部加载这些图片会使浏览器发送大量请求和造成浪费。采用懒加载技术,即用户浏览到哪儿,就加载该处的图片。这样节省网络资源、提升用户体验、减少服务器压力。


方法1:使用scrollTop/innerHeight/offsetTop

基本知识点:

window.innerHeight:浏览器可视区域高度
document.body.scrollTop || document.documentElement.scrollTop:浏览器滚动条滚过高度
img.offsetTop:元素距文档顶部的高度 

这里有张图可以非常清晰的理解上述概念:



加载条件:

img.offsetTop < window.innerHeight + document.body.scrollTop;

代码如下:

<script type="text/javascript">
	var imgs = document.querySelectorAll('img');
	window.onscroll = function(){
		var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
		var winTop = window.innerHeight;
		for(var i=0;i < imgs.length;i++){
			if(imgs[i].offsetTop < scrollTop + winTop ){
				imgs[i].src = imgs[i].getAttribute('data-src');
			}
		}
	}
</script>

函数节流:

<script type="text/javascript">
	var imgs = document.querySelectorAll('img');
	var lazyload = function(){
		var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
		var winTop = window.innerHeight;
		for(var i=0;i < imgs.length;i++){
			if(imgs[i].offsetTop < scrollTop + winTop ){
				imgs[i].src = imgs[i].getAttribute('data-src');
			}
		}
	}
	function throttle(method,delay){
		var timer = null;
		return function(){
			var context = this, args=arguments;
			clearTimeout(timer);
			timer=setTimeout(function(){
				method.apply(context,args);
			},delay);
		}
	}
	window.onscroll = throttle(lazyload,200);
</script>



方法2:使用IntersectionObserver方法

基础知识

var io = new IntersectionObserver(callback, option);
 
//开始观察
io.observe(document.getElementById('example'));
 
//停止观察
io.unobserve(element);
 
// 关闭观察器
io.disconnect();

上面代码中,构造函数IntersectionObserver接收两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。 这个构造函数的返回值是一个观察器实例。构造函数的返回值是一个观察器实例,实例的observe方法可以指定观察哪个DOM节点。

observe的参数是一个DOM节点对象。如果要观察多个节点,就要多次调用这个方法。 callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员。

intersectionRatio:目标元素的可见比例,完全可见时为1,完全不可见时小于等于0。 

 代码如下:

<script type="text/javascript">
	//获取观察器实例  changes是被观察的对象数组
	var observer = new IntersectionObserver(function(changes){  
		console.log(changes);
		changes.forEach(function(index,item){
			if(item.intersectionRatio > 0 && item.intersectionRatio < 1)
				//target:被观察的目标元素,是一个 DOM 节点对象
				item.target.src = item.target.dataset.src;
		});
	});
	function addObserver(){
		var listItems = document.querySelectorAll('.img-item');
		listItems.forEach(function(item){
			//实例的observe方法可以指定观察哪个DOM节点
			//开始观察  observe的参数是一个 DOM 节点对象
			observer.observe(item);
		});
	}
	addObserver();
</script>


完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>LozyLoad</title>
	<style>
		.images{
			display: flex;
			flex-direction: column;
			text-align: center;
			width: 500px;
		}
		.img-item{
			height:400px;
			width: 400px;
			margin: 20px;
		}

	</style>
</head>
<body>
	<div class="images">
		<img class="img-item" alt="loading" data-src="./img/img1.png">
		<img class="img-item" alt="loading" data-src="./img/img2.png">
		<img class="img-item" alt="loading" data-src="./img/img3.png">
		<img class="img-item" alt="loading" data-src="./img/img4.png">
		<img class="img-item" alt="loading" data-src="./img/img5.png">
	</div>
	<!--
	<script type="text/javascript">
		//获取观察器实例  changes是被观察的对象数组
		var observer = new IntersectionObserver(function(changes){  
			console.log(changes);
			changes.forEach(function(index,item){
				if(item.intersectionRatio > 0 && item.intersectionRatio < 1)
					//target:被观察的目标元素,是一个 DOM 节点对象
					item.target.src = item.target.dataset.src;
			});
		});
		function addObserver(){
			var listItems = document.querySelectorAll('.img-item');
			listItems.forEach(function(item){
				//实例的observe方法可以指定观察哪个DOM节点
				//开始观察  observe的参数是一个 DOM 节点对象
				observer.observe(item);
			});
		}
		addObserver();
	</script>
	-->
	<script type="text/javascript">
		var imgs = document.querySelectorAll('img');
		var lazyload = function(){
			var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
			var winTop = window.innerHeight;
			for(var i=0;i < imgs.length;i++){
				if(imgs[i].offsetTop < scrollTop + winTop ){
					imgs[i].src = imgs[i].getAttribute('data-src');
				}
			}
		}
		function throttle(method,delay){
			var timer = null;
			return function(){
				var context = this, args=arguments;
				clearTimeout(timer);
				timer=setTimeout(function(){
					method.apply(context,args);
				},delay);
			}
		}
		window.onscroll = throttle(lazyload,200);
	</script>
</body>
</html>



本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_2035