前端性能优化篇:图片懒加载图片的懒加载 首先,让我们来看传统的图片一次性全部加载; 它会一次性加载所有的图片,这对浏览器
随着互联网的发展,用户对网页加载速度的要求越来越高。尤其是在移动设备上,用户往往更关心页面的加载速度和数据流量的消耗;同时页面上的图片很多的情况下,如果不做优化处理,就容易导致页面的加载发生卡顿,今天我们就来学习一下对图片的懒加载处理。
图片的懒加载
首先,让我们来看传统的图片一次性全部加载;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
</body>
</html>
它会一次性加载所有的图片,这对浏览器的页面加载是不友好的。这是为什么呢?
浏览器会做什么?
这是因为浏览器的工作机制,当我们访问一个网页时;
- 解析HTML文档:浏览器从服务器获取HTML文档并开始解析,构建DOM树。
- 下载样式表:浏览器下载CSS样式表,并形成CSS树。
- 渲染页面:浏览器将DOM树和CSS树结合起来,生成渲染树,并最终绘制出可见的页面。
- 处理脚本:如果页面中有JavaScript脚本,浏览器会执行这些脚本。
虽然 JS 是单线程的,但是浏览器是多线程的;img
标签和 script
标签一样都会让浏览器启动新的下载线程去下载图片、JS 文件等;如果页面上同时让很多图片一起加载,那会让浏览器启动很多并发任务,增加浏览器的压力;这就犹如上高速,车流量如果太大,就容易造成堵塞。
实现懒加载
对于这种情况,我们就要进行性能优化处理了;我们只需要让浏览器加载首屏上的图片,而不用全部加载,并且图片的加载要随着滚动而进行懒加载;那我们要如何实现呢?
步骤:
要实现懒加载,我们需要手动控制图片的加载过程,而不是让浏览器自动下载所有的<img>
标签中的图片。
使用数据属性
将实际的图片地址存储在data-src
属性中,而非src
属性。
<img data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
通过数据属性data-src
,我们就可以人为地去控制图片的加载了。
监听滚动事件
添加一个事件监听器来检测页面滚动。
// 当DOM内容加载完成后执行
document.addEventListener('scroll', () => {
// 调用loadImage函数
loadImage();
});
图片懒加载
功能函数的实现:
// 定义 loadImage 函数
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 属性值(使用 data 属性)
imgs[i].src = imgs[i].getAttribute('data-src');
// 更新当前加载的图片索引
n = i + 1;
// 检查是否加载完所有需要懒加载的图片
if (n === num){
// 停止监听滚动事件,进行性能优化
window.removeEventListener('scroll', loadImage);
}
}
}
}
1. clientHeight
clientHeight
用于获取元素的可见高度(不包括边框、内边距和外边距)。此属性通常用于获取诸如窗口、文档或元素的高度。
2. scrollTop
scrollTop
用于获取或设置一个元素相对于其滚动容器的垂直滚动距离。这个值是从元素顶部到视口顶部的距离。
3. offsetTop
offsetTop
用于获取元素相对于最近的带有定位(positioned)祖先元素的顶部偏移量。如果没有定位的祖先,则相对于文档的顶部。
对懒加载进行防抖
由于滚动事件太敏感,容易高频触发懒加载函数loadImage
,我们可以给它添加一个防抖的优化操作,减少事件的触发。
工具库:
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<img data-price="20" 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>
// 获取页面中所有的img元素
const imgs = document.getElementsByTagName('img');
// 获取img元素的数量
const num = imgs.length;
// 记录当前加载的是第几张图片,从0开始
let n = 0;
// 当DOM完全加载后,执行loadImage函数
document.addEventListener('DOMContentLoaded', () => {
loadImage();
});
// 定义loadImage函数
function loadImage() {
console.log('121122');
// 获取可视区域的高度,兼容不同浏览器
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;
// 如果所有图片都已加载,则移除scroll事件的监听器,进行性能优化
if (n === num){
// console.log('加载完成');
// 所有图片加载完成后,移除功能函数
window.removeEventListener('scroll', throttleLazyLoad);
}
}
}
}
// 使用Lodash的throttle函数来延迟loadImage的执行,减少性能开销
const throttleLazyLoad = _.throttle(loadImage, 300);
// 添加scroll事件监听器,在滚动时执行throttleLazyLoad
window.addEventListener('scroll', throttleLazyLoad);
</script>
</body>
</html>
小结
图片懒加载是一项简单而有效的前端性能优化技术。传统的网页加载方式是一次性加载所有资源,这可能导致页面加载缓慢,特别是在移动设备或网络条件不佳的情况下。而懒加载则只在需要的时候(通常是当元素进入可视区域时)才加载相应的资源。通过合理控制图片的加载时机,不仅可以减少首屏加载时间,还可以降低服务器的压力,节省用户的数据流量。
转载自:https://juejin.cn/post/7402862738815156265