首页IT科技图片懒加载组件(【前端】图片懒加载的原理和三种实现方式)

图片懒加载组件(【前端】图片懒加载的原理和三种实现方式)

时间2025-05-01 22:52:21分类IT科技浏览3633
导读:一. 图片懒加载的目的 大型网站如常用的淘宝,京东等页面,需要展示大量的商品图片信息,如果打开网页时让所有图片一次性加载完成,需要处理很多次网络请求,等待加载时间比较长,用户体验感很差。...

一. 图片懒加载的目的

大型网站如常用的淘宝          ,京东等页面                 ,需要展示大量的商品图片信息      ,如果打开网页时让所有图片一次性加载完成        ,需要处理很多次网络请求                ,等待加载时间比较长         ,用户体验感很差            。

有一种常用的解决方式是:随着滚动动态加载      ,即图片的惰性加载                。视图之外的图片默认不加载                ,随着页面的滚动            ,图片进入了显示的范围   ,则触发图片的加载显示     。

优点:页面加载速度快                ,用户体验感更好且节省流量

二. 图片懒加载的原理方法

初始化时               ,图片标签的src不能是真实的图片地址,也不可以是空地址或者坏地址(会出现图片加载失败的图标)         。

初始化的时候             ,可以设置图片的src是某一个小型图片                 。例如一张1px*1px的透明图片       。由于所有图片都使用这一张图片                  ,只会发送一次请求   ,不会增加性能负担      。 将图片的真实路径绑定给一个自定义属性          ,例如data-url                  。注意:页面的img元素                 ,如果没有src属性      ,浏览器就不会发出请求去下载图片 <img data-url="xxx" src="1px.gif" width="100" height="100"/> 定义滚动事件        ,判断元素进入视口                ,则将src替换为真正的url地址          。利用js提取data-url的真实图片地址赋值给src属性

三. 图片懒加载的实现方法

图片懒加载的关键在于获取元素的位置         ,并判断其是否出现在视口   。故有以下三种方式

滚动监听+scrollTop+offsetTop+innerHeight 滚动监听+getBoundingClientRect() intersectionObserve()

3.1 滚动监听+scrollTop+offsetTop+innerHeight

scrollTop:指网页元素被滚动条卷去的部分                  。

offsetTop:元素相对父元素的位置

innerHeight:当前浏览器窗口的大小             。需要注意兼容性问题。

IE8及更早版本以前没有提供取得浏览器窗口大小的属性      ,不过提供了API:document.documentElement.clientHeight/clientWidth:返回元素内容及其内边距所占据的空间大小               。 IE6中                ,上述属性必须在标准模式才有效            ,如果是混杂模式   ,需要通过document.body.clientWidth 和 document.body. clientHeight 取得相同信息                。 var pageWidth = window.innerWidth var pageHeight = window.innerHeight; if (typeof pageWidth != "number"){ //pageWidth的值不是数值                ,说明没有innerwidth属性 if (document.compatMode == "CSS1Compat"){ //标准模式 pageWidth = document.documentElement.clientWidth; pageHeight = document.documentElement.clientHeight; } else { //混杂模式 pageWidth = document.body.clientWidth; pageHeight = document.body.clientHeight

; } } 三个属性之间的关系如图所示               ,故当scrollTop+innerHeight > offsetTop,即图片在视口内             ,否则图片在可视区域外   。

代码实现

滚动监听完成图片懒加载的简易版本

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } img { margin-top:400px; width: 250px; display: block; } </style> </head> <body> <img src="img/1pxImg.png" data-url="img/1.jpg"> <img src="img/1pxImg.png" data-url="img/2.jpg"> <img src="img/1pxImg.png" data-url="img/3.jpg"> <img src="img/1pxImg.png" data-url="img/4.jpg"> <img src="img/1pxImg.png" data-url="img/5.jpg"> <script> var imgs = document.getElementsByTagName(img) scrollFn() // 监听滚动事件 window.onscroll = scrollFn function scrollFn() { var clietH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; console.log(clietH, scrollTop); Array.from(imgs).forEach((item) =>{ let eleTop = item.offsetTop // console.log(eleTop) let count = scrollTop + clietH - eleTop console.log(count) // 可设置为>100 查看懒加载效果 if (count > 0) { //从data-url中取出真实的图片地址赋值给scr item.setAttribute(src, item.getAttribute(data-url)) } }) } </script> </body> </html>

3.2 滚动监听+getBoundingClientRect()

getBoundingClientRect()

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置            。返回一个对象                  ,对象属性包括top   ,right

rectObject = object.getBoundingClientRect();

API返回一个对象          ,即rectObject为一个对象                 ,其包含以下属性

rectObject.top:元素上边到视窗上边的距离; rectObject.right:元素右边到视窗左边的距离; rectObject.bottom:元素下边到视窗上边的距离; rectObject.left:元素左边到视窗左边的距离; rectObject.width:元素自身的宽度 rectObject.height:元素自身的高度 故当rectObject.top的值处于0-视口高度      ,则元素处于可视区                。即 getBoundingClientRect(ele).top >= 0 && getBoundingClientRect(ele).top <= offsetHeight

代码实现

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } img { margin-top:400px; width: 250px; display: block; } </style> </head> <body> <img src="img/1pxImg.png" data-url="img/1.jpg"> <img src="img/1pxImg.png" data-url="img/2.jpg"> <img src="img/1pxImg.png" data-url="img/3.jpg"> <img src="img/1pxImg.png" data-url="img/4.jpg"> <img src="img/1pxImg.png" data-url="img/5.jpg"> <script> var imgs = document.getElementsByTagName(img) scrollFn() // 监听滚动事件 window.onscroll = scrollFn function scrollFn() { var clietH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; Array.from(imgs).forEach((item) =>{ let ele = item.getBoundingClientRect() console.log(clietH,ele.top) // 可以设置为ele.top+200 查看懒加载效果 if (ele.top > 0 && ele.top < clietH) { //从data-url中取出真实的图片地址赋值给scr item.setAttribute(src, item.getAttribute(data-url)) } }) } </script> </body> </html>

3.3 intersectionObserve()

intersectionObserve()

新的API        ,针对元素的可见时间进行监听     。由于可见(visible)的本质是                ,目标元素与视口产生一个交叉区         ,所以这个 API 叫做"交叉观察器"         。

var io = new IntersectionObserver(callback, option);

IntersectionObserver是浏览器原生提供的构造函数      ,接受两个参数:callback是可见性变化时的回调函数                ,option是配置对象(该参数可选)                 。

构造函数的返回值是一个观察器实例       。实例的observe方法可以指定观察哪个 DOM 节点      。

// 开始观察 io.observe(document.getElementById(example)); // 停止观察 io.unobserve(element); // 关闭观察器 io.disconnect();

上面代码中            ,observe的参数是一个 DOM 节点对象                  。如果要观察多个节点   ,就要多次调用这个方法          。

io.observe(elementA); io.observe(elementB); callack参数

目标元素的可见性变化时                ,就会调用观察器的回调函数callback   。

一般会触发两次:1.目标元素刚刚进入视口(开始可见)               ,2.完全离开视口(开始不可见)                  。

callback函数的参数是一个数组,每个成员都是一个IntersectionObserverEntry对象             。

IntersectionObserverEntry 对象

提供目标元素的信息             ,一共有六个属性。

time:可见性发生变化的时间                  ,是一个高精度时间戳   ,单位为毫秒 target:被观察的目标元素          ,是一个 DOM 节点对象 rootBounds:根元素的矩形区域的信息                 ,getBoundingClientRect()方法的返回值      ,如果没有根元素(即直接相对于视口滚动)        ,则返回null boundingClientRect:目标元素的矩形区域的信息 intersectionRect:目标元素与视口(或根元素)的交叉区域的信息 intersectionRatio:目标元素的可见比例                ,即intersectionRect占boundingClientRect的比例         ,完全可见时为1      ,完全不可见时小于等于0

所以可以通过判断intersectionRatio属性是否处于(0,1)来判断元素的可见性

代码实现

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } img { margin-top:400px; width: 250px; display: block; } </style> </head> <body> <img src="img/1pxImg.png" data-url="img/1.jpg"> <img src="img/1pxImg.png" data-url="img/2.jpg"> <img src="img/1pxImg.png" data-url="img/3.jpg"> <img src="img/1pxImg.png" data-url="img/4.jpg"> <img src="img/1pxImg.png" data-url="img/5.jpg"> <script> var imgs = document.getElementsByTagName(img) // 观察器实例 let io = new IntersectionObserver((entires) =>{ entires.forEach(item => { // 原图片元素 let oImg = item.target if (item.intersectionRatio > 0 && item.intersectionRatio <= 1) { oImg.setAttribute(src, oImg.getAttribute(data-url)) } }) }) // 给每一个图片设置观察器 Array.from(imgs).forEach(element => { io.observe(element) }); </script> </body> </html>

备注:本文章为学习前端知识过程中的记录和分享                ,如有错误欢迎指正!

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
vue3使用不了过滤器怎么办(Vue–》过滤器介绍及其使用方法) 昆仑玻璃和康宁大猩猩玻璃哪个好(KunlunPlatform.exe是什么进程?KunlunPlatform.exe是安全的程序吗?)