图片懒加载(Lazy Load)及初步性能优化
图片懒加载(Lazy Load)及初步性能优化
在现代Web开发中,图片懒加载(Lazy Load)是一种非常有效的性能优化技术。它能够显著减少初次加载时间,提高用户体验。本文将深入探讨图片懒加载的原理、实现步骤及其在前端性能优化中的重要性。
浏览器的工作原理
要理解图片懒加载的意义,我们首先需要了解浏览器是如何加载和渲染网页的。以下是浏览器的主要工作步骤:
- 解析HTML:浏览器下载HTML文件并解析,建立DOM树(Document Object Model)。
- 下载CSS:解析和下载CSS文件,构建CSSOM树(CSS Object Model)。
- 渲染树:结合DOM树和CSSOM树,构建渲染树。
- 布局和绘制:计算每个元素的位置和大小,然后将内容绘制到屏幕上。
- 执行JavaScript:JavaScript是单线程的,但浏览器是多线程的,它会启动新的线程来下载和执行外部资源(如图片、脚本等)。
当浏览器解析到<img>
标签时,会立即启动新的下载线程来获取图片。过多的并发下载可能导致网络堵塞,影响页面加载速度。因此,有必要控制图片的加载时机,尤其是那些在初次渲染时并不在视窗内的图片。
性能优化策略
为了提高页面加载性能,前端开发人员通常采用以下策略:
- 优先加载首屏图片:确保初次加载时,用户可以立即看到主要内容。
- 滚动懒加载:当用户滚动页面时,才开始加载视窗内的新图片。
- 减少并发请求:限制同时进行的图片下载数量,以避免网络堵塞。
图片懒加载的实现步骤
手动控制图片加载
默认情况下,<img>
标签的src
属性一旦被设置,浏览器会立即下载该图片。为了实现懒加载,我们可以使用自定义属性(如data-src
)来存储图片的URL,并在需要时手动设置src
属性。
代码示例
HTML结构说明
<head>
部分引入了CSS文件和Lodash库。<body>
部分包含了10张图片,这些图片的src
属性没有被设置,而是使用data-src
属性存储图片的URL。- 使用了一个脚本来实现图片的懒加载。
JavaScript代码功能
-
变量声明:
imgs
:存储所有的图片元素。num
:图片的总数。n
:已加载图片的计数。
-
loadImage
函数:- 获取视窗高度(
screenHeight
)。 - 获取滚动条位置(
scrollTop
)。 - 遍历所有图片,检查每张图片是否进入视窗(通过比较
offsetTop
和screenHeight + scrollTop
)。 - 如果图片进入视窗,则将其
data-src
属性赋值给src
属性,从而触发图片加载。 - 更新已加载图片计数
n
,如果所有图片已加载完毕,则移除滚动事件监听器。
- 获取视窗高度(
-
throttleLayLoad
:- 使用Lodash的
throttle
函数对loadImage
函数进行节流处理,使其在500毫秒内最多执行一次。
- 使用Lodash的
-
事件监听器:
- 为
scroll
事件添加两个监听器:一个是经过节流处理的throttleLayLoad
,另一个是原始的loadImage
。
- 为
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入公共CSS文件 -->
<link rel="stylesheet" href="./common.css">
<!-- 引入Lodash库用于节流函数 -->
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<!-- 使用data-src属性存储图片URL以实现懒加载 -->
<img data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
<script>
// 获取所有图片元素
const imgs = document.getElementsByTagName('img');
const num = imgs.length; // 图片总数
let n = 0; // 已加载图片计数
// 懒加载图片的函数
function loadImage() {
let screenHeight = document.documentElement.clientHeight; // 视窗高度
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条位置
for (let i = 0; i < num; i++) {
// 检查图片是否进入视窗
if (imgs[i].offsetTop < screenHeight + scrollTop) {
// 设置图片src属性,触发加载
imgs[i].src = imgs[i].getAttribute('data-src');
n = i + 1;
// 如果所有图片已加载完毕,移除滚动事件监听器
if (n === num) {
window.removeEventListener('scroll', throttleLayLoad);
}
}
}
}
// 使用Lodash的节流函数,限制loadImage函数的执行频率
const throttleLayLoad = _.throttle(loadImage, 500);
// 添加滚动事件监听器,触发懒加载
window.addEventListener('scroll', throttleLayLoad);
window.addEventListener('resize', throttleLayLoad); // 添加窗口大小改变事件监听器
window.addEventListener('orientationchange', throttleLayLoad); // 添加屏幕方向改变事件监听器
// 页面加载完成后执行loadImage函数,确保首屏图片立即加载
document.addEventListener('DOMContentLoaded', loadImage);
</script>
</body>
</html>
CSS样式说明
-
全局清除默认的
margin
和padding
。 -
设置
body
的背景色为灰色。 -
设置
img
元素:display: block
:使图片成为块级元素,占据一整行。margin-bottom: 50px
:每张图片底部有50px的间距。width: 400px
和height: 400px
:统一设置图片的宽高为400px。
* {
margin: 0;
padding: 0;
}
body {
background-color: gray;
}
img {
display: block;
margin-bottom: 50px;
width: 400px;
height: 400px;
}
性能优化的收益
通过实现图片懒加载,我们可以显著提高页面的加载速度,特别是在图片较多的情况下。减少不必要的图片下载,避免网络拥塞,使用户在滚动页面时能更流畅地浏览内容。
浏览器底层原理
- 下载线程:浏览器会为每个资源(如图片、脚本、样式表)启动新的下载线程,并行下载加速页面加载。
- 并发数限制:浏览器对同一域名的并发请求数有限制(一般为6个),过多的并发请求会导致队列堵塞。
核心技术点
- clientHeight:视窗高度。
- scrollTop:滚动条顶部距离文档顶部的距离。
- offsetTop:元素距离文档顶部的距离。
- dataset:用于访问自定义数据属性(如
data-src
)。
转载自:https://juejin.cn/post/7379780178292195382