图片懒加载

在网上经常能看到性能优化关于图片懒加载的文章,自己没有真正的实践过,今天任务开发完,利用了下这个时间,便自己写了一个demo实现了简单的图片懒加载功能。实现的效果如下

20230511_205048.gif

说一下实现的思路
  1. 假设页面容器内需要放置多张图片列表,先在各个img标签上加上src=“默认未加载列表中展示的图片”,data-src=“后面加载需要用到的图片地址”。例如这样
 <img data-src="./assest/test.webp" src="./assest/default.webp"/>
 /**
    data-*属性是HTML5的新标签,
    它可以让我们在所有html元素上嵌入自定义数据属性的能力,
    后续我们便可以利用该属性在HTML和DOM之间实现专有数据交换。
  */
  1. 我们首先获取容器中图片列表的长度、容器的可视高度、以及单个img实例对应的高度。对clientHeight容器宽度高度属性还不清楚的建议可以看下这篇
// 获取图片列表长度
const length = document.getElementsByTagName("img").length;
// 获取图片示例
const img = document.getElementsByTagName("img");
// 获取容器实例
const pageContent = document.getElementsByClassName("page-content")[0];
// 获取可见区域高度
const clientHeight = pageContent.clientHeight;
// 获取单个img标签所占高度
const imgHeight = img[0].height;
// 用于判断容器内可见区域内可容纳多少张图片, 图片加载的位置
let index = Math.ceil(clientHeight / imgHeight);
// 页面初始化时的滚动距离,后续用于判断用户进行的是往下滚动还是向上滚动操作。只有向下滚动才需要去进行懒加载事件。
let beforeScrollTop = pageContent.scrollTop; 
  1. 定义一个懒加载方法,里面需要先获取滚动的距离。对于最上边的框距离可视区域的高度小于(可视区域高度 + 滚动的距离)的图片时,进行对应的懒加载赋值操作。把先前data-src属性值赋值给src属性。
function lazyLoad() {
        // 获取监听后滚动条距离顶部高度
        const scrollTop = pageContent.scrollTop;
	// 获取两次滚动的距离,用于判断浏览器是向上滚动还是向下滚动。向下滚动才触发加载事件。
	let isUpDown = scrollTop - beforeScrollTop;
        if (isUpDown < 0) {
            console.log("上滚");
            return;
        } else {
            console.log("下滚");
            beforeScrollTop = scrollTop;
            for(let i = 0; i < length; i ++) {		
                if (img[i].offsetTop < (clientHeight + scrollTop)) {
			if (img[i].getAttribute("src") === "./assest/default.webp") {					
                            img[i].src = img[i].getAttribute("data-src");
			}
			index = i + index;
                  }
             }
      }
}

4.这样已经能实现如文章开头的样子了,但是有一个问题就是,浏览器监听事件,只要我滚动就会去触发,这样很消耗性能。所以我们还可以加一个节流事件,让用户的滚动操作隔一段时间才触发。

function throttle(fn, delay) {
    let valid = true;
    return function() {
        if (valid) {
           setTimeout(() => {				
               fn.apply(this,arguments);
               valid = true;
	   }, delay);
        }
        valid = false;
     }
}
//最后再为该容器添加监听事件就好啦
pageContent.addEventListener("scroll", throttle(lazyLoad, 1000));
完整的代码在这里
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>图片懒加载</title>
	</head>
	<style>
		body{
			padding: 20px 0 0;
			margin: 0;
			background-color: antiquewhite;
			width: 100%;
			height: 100vh;
			display: flex;
			justify-content: center;
		}
		.page-content{
			width: 30%;
			height: 500px;
			background-color: white;
			padding: 20px;
			overflow: auto;
		}
		img{
			width: 100%;
			height: 200px;
			margin-bottom: 20px;
		}
	</style>
	<body>
		<div class="page-content">
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<img data-src="./assest/test.webp" src="./assest/default.webp"/>
			<script>
				// 获取图片列表长度
				const length = document.getElementsByTagName("img").length;
				// 获取图片示例
				const img = document.getElementsByTagName("img");
				// 获取容器实例
				const pageContent = document.getElementsByClassName("page-content")[0];
				// 获取可见区域高度
				const clientHeight = pageContent.clientHeight;
				// 获取单个img标签所占高度
				const imgHeight = img[0].height;
				// 用于判断容器内可见区域内可容纳多少张图片, 图片加载的位置
				let index = Math.ceil(clientHeight / imgHeight);
				// 页面初始化是的滚动距离
				let beforeScrollTop = pageContent.scrollTop; 
				lazyLoad();
				// 为容器添加滚动监听事件
				pageContent.addEventListener("scroll", throttle(lazyLoad, 1000));
				function lazyLoad() {
					// 获取监听后滚动条距离顶部高度
					const scrollTop = pageContent.scrollTop;
					// 获取两次滚动的距离,用于判断浏览器是向上滚动还是向下滚动。向下滚动才触发加载事件。
					let isUpDown = scrollTop - beforeScrollTop;
					console.log(beforeScrollTop, scrollTop, isUpDown)
					if (isUpDown < 0) {
						console.log("上滚");
						return;
					} else {
						console.log("下滚");
						beforeScrollTop = scrollTop;
						for(let i = 0; i < length; i ++) {
							console.log(img[i].offestTop, clientHeight, scrollTop)
							if (img[i].offsetTop < (clientHeight + scrollTop)) {
								if (img[i].getAttribute("src") === "./assest/default.webp") {
									img[i].src = img[i].getAttribute("data-src");
								}
								index = i + index;
							}
						}
					}
				}
				function throttle(fn, delay) {
					let valid = true;
					return function() {
						if (valid) {
							setTimeout(() => {
								fn.apply(this,arguments);
								valid = true;
							}, delay);
						}
						valid = false;
					}
				}
			</script>
		</div>
	</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值