Javascript 图片懒加载

server/2024/12/2 21:31:12/

摘要

最近公司和第三方材料供应商对接开发了物资集采平台,其中有个功能需求需要展示数百张材料信息图片,有时页面会出现卡顿的情况,并使用了图片懒加载的方式进行了优化。下面把方法分享给大家一起学习。

未做优化实例

以下代码仅作为示例演示给大家看,不是公司内部代码。

<!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>

一次性加载所有的图片,这对浏览器的页面加载是不友好的。

浏览器的工作机制

1.首先了解一下浏览器的运行机制

当我们访问一个网页时

  • 解析HTML文档:浏览器从服务器获取HTML文档并开始解析构建DOM树
  • 下载样式表:浏览器下载CSS样式表,并形成CSS树
  • 渲染页面:浏览器将DOM树和CSS树结合起来,生成渲染树,并最终绘制出可见的页面。
  • 处理脚本:如果页面中有JavaScript脚本,浏览器会执行这些脚本。

2.虽然 JS 是单线程的,但是浏览器是多线程的;img 标签和 script 标签一样都会让浏览器启动新的下载线程去下载图片、JS 文件等;如果页面上同时让很多图片一起加载,那会让浏览器启动很多并发任务,增加浏览器的压力;这就犹如上高速,车流量如果太大,就容易造成堵塞

懒加载

要实现懒加载,我们需要手动控制图片的加载过程,而不是让浏览器自动下载所有的<img>标签中的图片。

1.使用数据属性

将实际的图片地址存储在data-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">
2.监听滚动事件
javascript">        // 当DOM内容加载完成后执行document.addEventListener('scroll', () => {// 调用loadImage函数loadImage();});
3.功能函数的实现
javascript">        // 定义 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);}}}}
  • clientHeight 用于获取元素的可见高度(不包括边框、内边距和外边距)。此属性通常用于获取诸如窗口、文档或元素的高度
  • scrollTop 用于获取或设置一个元素相对于其滚动容器的垂直滚动距离。这个值是从元素顶部到视口顶部的距离
  • offsetTop 用于获取元素相对于最近的带有定位(positioned)祖先元素的顶部偏移量。如果没有定位的祖先,则相对于文档的顶部

优化:懒加载进行防抖

由于滚动事件太敏感,容易高频触发懒加载函数loadImage,我们可以给它添加一个防抖的优化操作,减少事件的触发。

工具库

javascript"><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事件监听器,在滚动时执行throttleLazyLoadwindow.addEventListener('scroll', throttleLazyLoad);</script>
</body>
</html>

总结

图片懒加载是一项简单而有效的前端性能优化技术,欢迎大家一起讨论其他更好的方法。


http://www.ppmy.cn/server/146842.html

相关文章

【西瓜书】决策树

决策树 决策树&#xff08;decision tree&#xff09;是一种常见的机器学习方法&#xff0c;也叫“判定树”。 根据上下文&#xff0c;决策树有时候是指学习方法&#xff0c;有时候是指学得的树。 决策树是根据树形结构来进行决策的&#xff0c;这与人类在面临决策问题时的处…

matlab2024a安装

1.开始安装 2.点击安装 3.选择安装密钥 4.接受条款 5.安装密钥 21471-07182-41807-00726-32378-34241-61866-60308-44209-03650-51035-48216-24734-36781-57695-35731-64525-44540-57877-31100-06573-50736-60034-42697-39512-63953 6 7.选择许可证文件 8.找许可证文件 9.选…

springboot340“共享书角”图书借还管理系统(论文+源码)_kaic

摘 要 随着社会的发展&#xff0c;图书借还的管理形势越来越严峻。越来越多的借阅者利用互联网获得信息&#xff0c;但图书借还信息量大。为了方便借阅者更好的获得本图书借还信息&#xff0c;因此&#xff0c;设计一种安全高效的“共享书角”图书借还管理系统极为重要。 为…

v-for产生 You may have an infinite update loop in a component render function

参考文章&#xff1a; 报错解析 [Vue warn]: You may have an infinite update loop in a component render function. 另外一个解决方法 例如: MyList 是一个数组&#xff0c;我希望将排序后的结果返回进行for循环&#xff0c;因此设计了一个myMethon函数 <div v-for"…

Linux系统硬件老化测试脚本:自动化负载与监控

简介&#xff1a; 这篇文章介绍了一款用于Linux系统的自动化硬件老化测试脚本。该脚本能够通过对CPU、内存、硬盘和GPU进行高强度负载测试&#xff0c;持续运行设定的时长&#xff08;如1小时&#xff09;&#xff0c;以模拟长时间高负荷运行的环境&#xff0c;从而验证硬件的稳…

[Linux] 进程间通信——匿名管道命名管道

标题&#xff1a;[Linux] 进程间通信——匿名管道&&命名管道 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、进程间通信 二、进程间通信的方案——匿名管道 &#xff08;1&#xff09;匿名管道的原理 &#xff08;2&#xff09;使用匿名管道 三、进…

Qt中QSpinBox valueChanged 信号触发两次

Qt中QSpinBox valueChanged 信号触发两次 如果使用鼠标调整&#xff0c;这个信号则会被触发两次如果使用键盘输入&#xff0c;则会触发一次 connect(ui->spinBox_rows, SIGNAL(valueChanged(int)), this, SLOT(test()));https://blog.csdn.net/dododododoooo/article/deta…

【大数据学习 | Spark】Spark on hive与 hive on Spark的区别

1. Spark on hive Spark on hive指的是使用Hive的元数据&#xff08;Metastore&#xff09;和SQL解析器(HiveQL)。这种方式下&#xff0c;spark可以读取和写入hive表&#xff0c;利用hive的元数据信息来进行表结构的定义和管理。 具体特点为&#xff1a; 1.1 元数据共享 sp…