什么是懒加载?
懒加载,顾名思义,就是在当前网页,滑动页面到图片出现在可见区域的时候再加载图片,所以问题就可分解为以下两方面:
- 如何判断图片出现在了可见区域
- 如何控制图片的加载
1.如何判断图片出现在了可见区域
可以监听window.scroll
事件,通过clientTop
,offsetTop
,clientHeight
以及 scrollTop
各种关于图片的高度作对比。
2.如何控制图片的加载
监听window.scroll
事件的过程中,当满足条件时动态设置<img>
标签的src
属性就可以了。
以上简要的介绍了实现的原理,不过具体实现的时候有很多可以优化的地方。
1.优化判断图片出现在了可见区域
引入了一个新的api,Element.getBoundingClientRect()
方法能快速返回元素的大小及其相对于视口的位置,拿页面上的body
举例
console.log(document.body.getBoundingClientRect());
//DOMRect {
// bottom: 0
// height: 0
// left: 0
// right: 1920
// top: 0
// width: 1920
// x: 0
// y: 0
//}
2.优化window.scroll监听事件
加个节流器,提高性能。工作中一般使用lodash
库里的 lodash.throttle
就可以了。(什么是节流?可见 什么是防抖和节流)
3.同时优化判断图片出现在了可见区域和window.scroll监听事件
以上的思路我们可以看出主要过程是通过window.scroll
监听 Element.getBoundingClientRect()
并使用 lodash.throttle
节流。这一系列组合动作太复杂了,于是浏览器出了一个三合一事件: IntersectionObserver API
,一个能够监听元素是否到了当前视口的事件,一步到位!事件回调的参数是 IntersectionObserverEntry
的集合,代表关于是否在可见视口的一系列值,其中change.isIntersecting
代表目标元素可见
const observer = new IntersectionObserver((changes)=>{
// changes: 目标元素集合
changes.forEach((change) => {
// intersectionRatio
if (change.isIntersecting) {
const img = change.target
img.src = img.dataset.src
observer.unobserve(img)
}
})
})
observer.observe(img)
终究优化方案
浏览器觉得懒加载这事可以交给自己做,你们开发者加个属性就好了。
<img src="XXX.jpg" loading="lazy">
不过目前浏览器兼容性不太好,目前除了chrome几乎都不支持。