实战项目中的必须要会的技能点!——图片懒加载
前言
在互联网时代,用户体验是衡量网站质量的重要标准之一,而网页加载速度直接影响着这一体验。图片作为网页内容的主要组成部分,其加载效率对页面的整体表现至关重要。这就是为什么“图片懒加载”技术应运而生,它通过延迟非首屏图片的加载时间,显著提升了网页的初始加载速度,从而改善了用户体验和提高了搜索引擎优化(SEO)。
正文
我们在写这样一个网页时,有没有考虑过浏览器是如何执行的?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./common.css">
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>
<body>
<img src="https://img0.baidu.com/it/u=3422287847,344441285&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1718384400&t=f58a767d4eeaf746cc327920a84e7276" />
<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>
浏览器的工作流程
当用户访问一个网页时,浏览器会执行一系列复杂的操作来呈现页面内容:
1. 请求与接收
- 用户输入网址: 用户在浏览器地址栏输入URL或点击链接,浏览器发起HTTP/HTTPS请求。
- 域名解析: 浏览器通过DNS解析将网址转换为服务器的IP地址。
- 建立连接: 使用TCP三次握手与服务器建立连接。
- 发送HTTP请求: 浏览器向服务器发送HTTP请求,包含请求方法(如GET或POST)、请求头、请求正文等。
- 接收HTTP响应: 服务器处理请求后,返回HTTP响应,包括状态码、响应头、响应体(通常是HTML文档)。
2. 解析HTML文档
- 构建DOM树: 浏览器接收到HTML文档后,开始解析HTML代码,将标签解析成一系列的节点,并构建Document Object Model(DOM)树。
- 加载CSS和JavaScript: 浏览器解析HTML时遇到
<link>
、<style>
、<script>
等标签,会暂停HTML解析(对于同步加载的脚本),去下载并执行CSS和JavaScript文件。
3. 渲染流程
- 构建CSSOM: 对于CSS文件,浏览器会构建CSS Object Model(CSSOM),这是一个表示样式规则的树状结构。
- 合并DOM与CSSOM: 将DOM树和CSSOM树合并,形成渲染树(Render Tree),该树只包含需要渲染到屏幕上的元素及其对应的样式。
- 布局(Layout) : 根据渲染树计算每个节点在屏幕上的确切位置和尺寸,这个过程称为布局或重排。
- 绘制(Paint) : 最后,浏览器根据渲染树和布局信息,将各个节点绘制到屏幕上,完成像素渲染。
4. JavaScript执行与交互
- 解析与执行: 当JavaScript文件被下载后,浏览器的JavaScript引擎开始解析和执行代码。这可能修改DOM、CSSOM,导致重新布局和绘制。
- 异步处理: 对于异步操作如Ajax请求、Promise、setTimeout等,浏览器通过事件循环和回调队列来管理,不影响主线程的执行。
5. 网络资源管理
- 图片和其他资源加载: 浏览器在渲染过程中遇到图片或其他媒体资源,会并发地发送请求下载这些资源。通常,浏览器会对并发请求数量进行限制(比如Chrome限制为6个TCP连接)以避免网络拥塞。
- 缓存机制: 为了提高性能,浏览器会缓存静态资源,如图片、CSS、JavaScript文件等,后续请求相同资源时可以直接从本地缓存读取,无需再次下载。
6. 用户交互与动态更新
- 事件监听: 浏览器负责监听用户的各种交互,如点击、滚动、键盘输入等,并触发相应的JavaScript事件处理函数。
- 动态渲染: JavaScript可以实时修改DOM和CSSOM,导致页面内容和样式的更新,浏览器会根据这些变化重新执行布局和绘制流程。
在这一系列的事情过后,一个较为完整的页面就呈现了出来
这里是11张照片,但是如果是100张,1000张呢?
图片的资源请求是并发的,一旦有如此多的请求就会发生堵塞,,如果所有图片都立即加载,不仅会占用宝贵的网络带宽,还会延长页面的初始加载时间。因此,性能优化成为必然:
- 首屏优先:确保用户第一眼看到的内容(视窗内的图片)迅速加载。
- 滚动懒加载:仅在图片即将进入可视区域时才开始加载,减少不必要的资源消耗。
- 快速反馈:前端工程师的首要目标是尽快展示页面内容,提升用户感知速度。
如何做?
传统方式中,图片通过<img src="image.jpg">
直接加载。懒加载则利用data-src
属性来存储实际图片地址,而src
则可设置为空或占位图。
我们先将图片的标签属性改为数据属性
<img data-src="https://img0.baidu.com/it/u=3422287847,344441285&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1718384400&t=f58a767d4eeaf746cc327920a84e7276" />
<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">
然后开始写js代码
先定义基础变量,再附上事件监听,改为当"DOM树"生成完毕后执行
const imgs = document.getElementsByTagName('img');
const num = imgs.length;
let n = 0;
document.addEventListener('DOMContentLoaded',()=>{
loadImage();
});
我们怎么知道滑到了哪张图片的位置呢?
很简单,我们能够获取整屏的高度screenHeight
并且能够获取滚动条当前滑动的距离scrollTop
再计算图片距离屏幕顶部的距离offsetTop
便能判断是否在当前位置
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){
//数据属性 dataset
imgs[i].src = imgs[i].getAttribute('data-src');
n = i+1;
if(n === num) {
//判断加载完毕
window.removeEventListener('scroll',throttleLayLoad
);
}
}
}
}
const throttleLayLoad = _.throttleLayLoad(loadImage,300);
window.addEventListener('scroll',loadImage);
最后我们为了防止一直滑动导致加载阻塞,我们需要将加载间隔设为0.3s,非常能够考虑到用户的实际体验。
总结
- 深入理解前端性能优化:图片懒加载是前端性能优化的一个重要方面,体现了对用户体验的重视。
- 掌握浏览器工作原理:理解浏览器如何处理资源下载、渲染及并发限制(TCP/IP连接数)。
- 技术细节:熟练运用
dataset
获取自定义数据属性,以及使用clientHeight
,scrollTop
,offsetTop
进行位置判断。 - 业务逻辑优化:减少事件监听器的触发次数(如在图片加载完成后移除
scroll
事件监听),优化图片数组遍历逻辑(避免每次滚动都遍历全部图片)。
通过图片懒加载技术,我们不仅优化了网页的加载速度,还提升了用户体验,是现代网页开发中不可或缺的性能提升策略。随着技术的演进,懒加载也逐渐集成到各种前端框架和库中,使得实现更为便捷高效。
求点赞评论收藏,有问题随时私信博主!
转载自:https://juejin.cn/post/7379995743883903013