文章目录
-
一、前言
二、关联知识点
1、HTML5的`data-*`
2、防抖和节流
二、`getBoundingClientRect()`实现懒加载
1、API介绍
2、懒加载实现
三、`IntersectionObserver`实现懒加载
1、API
2、懒加载实现
四、css属性loading实现懒加载
1、API
2、懒加载实现
五、总结
一、前言
什么是懒加载?
懒加载顾名思义,相对于正常资源的加载显得不那么勤快;只会在页面中需要用的时候才去加载相应资源,这样的好处是能够减少页面加载时的不必要的请求,减轻浏览器请求负担,给予用户更好的体验!
在前端开发中,懒加载十分有必要,很多第三方的组件库/js库都具备了懒加载的特性。最常见的就是图片的懒加载,本文就围绕图片的懒加载实现展开,介绍三种图片懒加载的实现方式:
1、基于
getBoundingClientRect()
的懒加载方式;2、基于
IntersectionObserver
的懒加载方式;3、基于
css属性loading
的懒加载方式;
其原理为:
1、判断元素是否在浏览器视口中;
2、监听浏览器滚动事件(
scroll
);3、当元素滚动出现在视口中时,进行资源加载`
二、关联知识点
1、HTML5的data-*
开发者喜欢在HTML标签
上添加自定义属性来存储和操作数据
。但这样做的问题是,你不知道将来会不会有其它脚本把你的自定义属性给重置掉,此外,你这样做也会导致html语法上不符合Html规范,以及一些其它副作用。于是HTML5
规范里增加了一个自定义data属性
,你可以拿它做很多有用的事情。
定义和用法:
data-*
属性用于存储私有
页面后应用的自定义数据
。
data-*
属性可以在所有的 HTML 元素
中嵌入数据。
element.getAttribute("data-*")
可以获取html标签中定义的数据;
element.dataset.*
可以获取html标签中定义的数据;
2、防抖和节流
(后续补充完整内容)
二、getBoundingClientRect()
实现懒加载
当在使用一个不常使用/看到的API时,保持先查看Can I Use,再决定是否使用的好习惯;从图中可以看到几乎所有的浏览器的版本都是支持getBoundingClientRect
的,那么就可以不用考虑兼容性问题放心使用了:
1、API介绍
Element.getBoundingClientRect()
方法返回元素的大小及其相对于视口的位置。
返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有left, top, right, bottom, x, y, width, 和 height这几个以像素为单位的只读属性用于描述整个边框。除了width 和 height 以外的属性是相对于视图窗口的左上角来计算的。
2、懒加载实现
实现步骤:
1)通过
ele.getBoundingClientRect().top
获取元素到视口高度;2)通过
document.documentElement.clientHeight
获取视口的高度;3)判断元素是否在视口中,如果出现在视口中对资源进行加载;
4)监听浏览器滚动
scroll
事件,并且在监听中重复步骤1-3;
代码如下:
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>懒加载title><style>.imglazy {margin-top: 800px;}style><script>// 方式一:使用getBoundingClientRect获取元素与视口的高度,判断元素是否在视口内,在监听滑动事件对元素属性进行修改;let laodingImg = () => {let ele = document.getElementById("lala");let ch = document.documentElement.clientHeight;let eh = ele.getBoundingClientRect().top;
console.log(eh);if (ch > eh) {//使用元素的dataset获取自定义的私有数据,也就是图片真正的地址,并将其赋值给img的src属性进行资源请求
ele.src = ele.dataset.src;}};
window.onload = () => {laodingImg();};//建议进行节流处理(此处为了方便就不做处理)
window.onscroll = () => {laodingImg();};script>head><body>
/*使用src存放私有的自定义数据,真正的图片请求地址*/<imgid="lala"class="imglazy"src="https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg"alt="123"/>body>html>
执行结果如下图:当没有滚动鼠标时,图片不在视口内,Network
中并没有对图片进行请求,当滚动鼠标直至img元素
出现在视口中,进行图片资源请求,显示图片。
三、IntersectionObserver
实现懒加载
查看Can I Use
中IntersectionObserver
的兼容性:
1、API
IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。
当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦IntersectionObserver被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。
使用方法:var io = new IntersectionObserver(callback, option);
// 开始观察
io.observe(document.getElementById(‘example’));
// 停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();
callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象
可以简单的理解为:
IntersectionObserver
是一个能够监听元素是否到了当前视口的事件!
IntersectionObserverEntry提供观察元素的信息,有七个属性。intersectionRatio和isIntersecting是用来判断元素是否可见的
boundingClientRect 目标元素的矩形信息
intersectionRatio 相交区域和目标元素的比例值 intersectionRect/boundingClientRect 不可见时小于等于0
intersectionRect 目标元素和视窗(根)相交的矩形信息 可以称为相交区域
isIntersecting 目标元素当前是否可见 Boolean值 可见为true
rootBounds 根元素的矩形信息,没有指定根元素就是当前视窗的矩形信息
target 观察的目标元素
time 返回一个记录从IntersectionObserver的时间到交叉被触发的时间的时间戳
2、懒加载实现
直接上代码:
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>懒加载title><style>.imglazy {margin-top: 800px;}style><script>//方式二
window.onload = ()=>{let ele = document.getElementById("lala");//使用IntersectionObserver创建实例let observer = new IntersectionObserver(changes =>{//遍历包含的IntersectionObserverEntry
changes.forEach(change => {
console.log(change.isIntersecting);//判断是否出现在视口if(change.isIntersecting){let img = change.target;
img.src = img.dataset.src;//加载完卸载observer实例
observer.unobserve(img)}});})//调用实例
observer.observe(ele)}script>head><body><imgid="lala"class="imglazy"src="https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg"alt="123"/>body>html>
结果如下:
四、css属性loading实现懒加载
Can I Use:css的loading属性兼容性并不好,总体只有72%
;并且chrome中也是最近的版本才采用了!(不推荐使用
,但是还是要介绍下)
1、API
HTML元素
延迟加载属性 ——
loading属性值lazy
允许浏览器选择性加载IMG元素,根据用户滚动操作至其元素附近执行加载,一定程度起到节流的作用;
2、懒加载实现
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>懒加载title><style>.imglazy {margin-top: 800px;}style>head><body><imgclass="imglazy"loading="lazy"src="https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg"alt="123"/>body>html>
但是呢,我在chrome中使用loading="lazy"并没有实现懒加载,电脑上的chrome版本为87,这也再次印证就目前来看,loading="lazy"的兼容性实在不好:
五、总结
综合上述,可以看到:
getBoundingClientRect
懒加载方式代码量最大(其实也不是很多),但是兼容性和使用率是最高的(推荐
);IntersectionObserver
懒加载方式相对而言是体验最好的,其结合监听和节流一体,体验最好,代码量不多,兼容性也好(十分推荐
);css的laoding
懒加载方式,虽然代码最简单,只需要添加一个属性就可以,但是兼容性太差,就目前来看不适合使用
;
欢迎大家关注本人的微信公众号,微信公众号将不定期发送相应学习文章和教程