【我眼中的】 - 【7】图片懒加载

图片懒加载,顾名思义,就是滑动页面到能看到图片的时候再加载图片。

对于图片懒加载而言,可以分为两部分进行考虑:①判断图片进入到可视窗口 ②控制图片进行加载

0. 为什么懒加载?

对于首屏之外的内容,特别是图片和视频,一方面由于资源文件很大,若是全部加载完成,既费时又费力,还容易阻塞渲染引起卡顿;另一方面,就算加载完成用户也不一定浏览到全部内容,如果首屏没有吸引到用户,很可能整个页面都会被关闭。
所以,在首次打开网站时,应尽量只加载首屏内容,首屏之外的图片或视频可以等到用户滑动到的时候再加载。

1. 实现方式:

方式一:位置计算 + 监听滚动事件 + DataSet API

👉 判断图片出现在窗口中需要用到clientTopoffsetTopclientHeight 以及 scrollTop 各种关于图片的高度作比对

(一堆东西也记不住,不如,放过自己?)

👉 监听 window.scroll 事件

👉 控制图片加载

<img data-src="shanyue.jpg">

首先设置一个临时 Data 属性 data-src,控制加载时使用 src 代替 data-src,可利用 DataSet API 实现

img.src = img.datset.src

方式二:getBoundingClientRect API + Scroll with Throttle + DataSet API

👉 getBoundingClientRecy()函数获取元素的相对位置。
getBoundingClientRecy().top 、 getBoundingClientRecy().bottom 、 getBoundingClientRecy().left 、 getBoundingClientRecy().right
位置如下所示:

如何判断图片出现在了当前视口?

img.getBoundingClientRect().top < document.documentElement.clientHeight

👉 优化window.scroll事件
加个节流器,提高性能。工作中一般使用 lodash.throttle 就可以了。

_.throttle(func, [wait=0], [options={}])

👉 控制图片加载 同方式一

方式三:IntersectionObserver API + DataSet API

⚡ 方案二使用的方法是: window.scroll 监听 Element.getBoundingClientRect() 并使用 _.throttle 节流

👉 一系列组合动作太复杂了,于是浏览器出了一个三合一事件: Intersection Observer API,一个能够监听元素是否到了当前视口的事件,一步到位!

关于Intersection Observer API的简述:
每当因页面滚动或者窗口尺寸发生变化,使得目标元素(target)与设备视窗或其他指定元素产生交集时,便会触发Intersection Observer API配置的回调函数,在该回调函数中进行延迟加载的逻辑处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
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)

方式四:LazyLoading属性

浏览器觉得懒加载这事可以交给自己做,你们开发者加个属性就好了。缺点就是兼容性存在问题。
<img src="shanyue.jpg" loading="lazy">

文章作者: qinwei
文章链接: https://qw-null.github.io/2022/05/24/7-我眼中的-图片懒加载/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 QW's Blog