Web性能优化之——图片懒加载(lazyload)

本文介绍了图片懒加载的概念,即延迟加载非可视区域的图片,以提高网页性能。文章详细阐述了实现懒加载的三个步骤,并探讨了window.innerHeight、Element.getBoundingClientRect()和防抖函数throttle在其中的作用。通过理解这些技术和方法,读者可以自己实现一个简单的图片懒加载功能。

一、什么是图片懒加载

图片懒加载,就是图片延迟加载。只加载页面可视区域上的图片,等滚动到页面下面时,再加载对应视口上的图片

二、懒加载的实现

图片的懒加载可以通过以下三个步骤实现

  • 一开始不给img元素的src属性赋值,这样就不会加载图片元素了
  • 当img元素出现在用户的浏览器视窗上,就给img的src属性赋值,加载图片
  • 通过防抖函数减少用户反复滚动页面造成的性能浪费
  • 如下图所示
    在这里插入图片描述
    在实现图片懒加载之前,我们需要先了解几个函数或属性
1、window.innerHeight

window.innerHeight属性,声明了窗口的文档显示区的高度和宽度,即当前可视区域的高度。
IE 不支持这些属性。它用 document.documentElement 或 document.body (与 IE 的版本相关)的 clientWidth 和 clientHeight 属性作为替代。

如下图
在这里插入图片描述

2、ELement.getBoundingClientRect()

getBoundingClientRect()用于获取某个元素相对于视窗的位置集合。集 合中有top, right, bottom, left等属性。

如下图所示。
在这里插入图片描述

3、防抖函数throttle

防抖函数是为了减少在短时间内用户多次触发某事件而造成的性能浪费。例如最近流行的“重要的事情讲三遍遍遍”,其实只听第一次就够了,后面两次无疑会造成大脑的性能浪费。那要如何减少这种浪费呢?
解决的方案是我们可以设置一个定时器,在听到第一遍“重要的事”后,我们就开启定时器,让大脑放空两秒钟,期间对再次发来的消息充耳不闻,两秒钟后,再继续接收消息。

代码如下

// 节流函数 -- 第一个人说了算
function throttle(func, delay = 2000) {
    // func -- 重要的事情  delay -- 大脑放空时间
let timer = null
    
return function() {
let context = this // 保存上下文环境
let args = arguments // 保存参数

        if(!timer) {
            // 这是timer为null,说明是第一次听到"重要的事"
            func.apply(context, args)
            // 开始放空...
            timer = setTimeout(() => {
                // 两秒钟过了 停止放空
                clearTimeout(timer)
                // 注意setTimeout会返回一个id,因此要再次让timer为null
                timer = null
            }, delay)
        }
    }
}

Ok,了解了以上属性和方法后,根据上面的实现原理,我们就可以实现一个简单的实现图片懒加载了!

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<title>Lazy-Load</title>
		<style>
			.img-item {
      width: 200px;
      height:200px;
      border-radius: 10px;
			/* 图片未加载时的背景图 */
      background-image: url(images/Loading02.gif);
			background-size: 200%;
			background-position: center;
			overflow: hidden;
    }
    .img {
			width: 100%;
			height: 100%;
    }
  </style>
	</head>
	<body>
		<div class="container">
			<div class="img-item">
				<!-- data-src属性用于保存图片src -->
				<img class="img" data-src="./images/panda.jpg">
			</div>
			<div class="img-item">
				<img class="img" data-src="./images/solider.jpg">
			</div>
			<div class="img-item">
				<img class="img" data-src="./images/solider2.jpg">
			</div>
			<div class="img-item">
				<img class="img" data-src="./images/s4.jpg">
			</div>
			<div class="img-item">
				<img class="img" data-src="./images/s4.jpg">
			</div>
			<div class="img-item">
				<img class="img" data-src="./images/s5.jpg">
			</div>
		</div>
		<!-- <script src="../防抖与节流/throttle.js" type="text/javascript" charset="utf-8"></script> -->
		<script type="text/javascript">
			// 获取所有的图片标签
			const imgs = document.getElementsByTagName('img')
			// 当前视口的高度
			const vh = window.innerHeight || document.documentElement.clientHeight
			// num用于统计避免每次都从第一张图片检查
			let num = 0

			function lazyload() {
				console.log('lazyload')
				for (let i = num; i < imgs.length; i++) {
					// 获取该img相对于视口的位置
					let imgTop = imgs[i].getBoundingClientRect().top
					// 元素距离视口顶端高度小于或等于视口高度,说明元素露出
					if (vh >= imgTop) {
						// 给img的src属性赋值
						imgs[i].src = imgs[i].getAttribute('data-src')
						num = i + 1
					}
				}
			}

			// 节流函数
			function throttle(func, delay = 2000) {
				// func -- 重要的事情
				// delay -- 大脑放空时间
				let timer = null

				return function() {
					if (!timer) {
						// 这是timer为null,说明是第一次听到"重要的事"
						func.apply(this, arguments)
						// 开始放空...
						timer = setTimeout(() => {
							// 两秒钟过了 停止放空
							clearTimeout(timer)
							// 注意setTimeout会返回一个id,因此要再次让timer为null
							timer = null
						}, delay)
					}
				}
			}

			const better_lazyLoad = throttle(lazyload, 200)
			console.log(better_lazyLoad)

			// 监听Scroll事件 页面加载完后要先加载一次图片
			window.onscroll = window.onload = better_lazyLoad
			// window.addEventListener('scroll', better_lazyLoad, false);
		</script>
	</body>
</html>

效果如下
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值