图片懒加载原理
欢迎阅读,本文将介绍图片懒加载的两种方式。
前言
目前项目中需要加载的图片很多,我们知道服务器请求次数过多,势必会影响到性能。为提高网页性能,需要实现图片的“按需加载”(图片懒加载),即图片默认暂时不加载,当图片即将进入可视区域时,再进行加载。
原理
当 <img>
的 src 的值存在时,浏览器发送请求,若没有 src
,则不发送请求。所以我们在使用 <img>
标签时,可以先在 src
里放置一张默认 loading 图,真实的图片地址以数组的形式存放在其 data-src
属性中,如:
1 |
|
当图片进入可视区域时,用 data-src
的值替换 src
里的默认值,从而实现图片的按需加载
实现方法
实现的重点是怎么判断图片是否在可视区域。
方法一:
使用 IntersectionObserver
API,可以自动“观察”元素是否在可视区域,但此方法兼容性较差,目前 Chrome 只兼容到 Chrome 51+
方法二:
监听 scroll
事件,调用目标元素的 getBoundingClientRect()
方法,得到该元素对应于“可视区域”左上角的坐标,再判断其是否在“可视区域”内,但操控滚动条时,会频繁操作DOM,容易造成性能问题,需要进行函数节流(请参考:http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html)。
实现
方法一:
浏览器提供的原生构造函数 IntersectionObserver
有两个参数:callback
回调函数,option
配置项(可选)
1 |
|
开始观察:io.observe(document.getElementById('example'))
;
停止观察:io.unobserve(element)
;
关闭观察器:io.disconnect()
;
这里需要注意:io.observe()
每次观察一个DOM节点对象,如果需要观察多个,需要调用多次。
callback参数
目标元素可见性发生变化时,会调用 callback
函数,callback
函数的参数(entries)
是一个数组,每个成员都是一个IntersectionObserverEntry
对象,该对象提供目标元素的信息,一共有六个属性:
time
:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒target
:被观察的目标元素,是一个 DOM 节点对象rootBounds
:根元素的矩形区域的信息,getBoundingClientRect()
方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回nullboundingClientRect
:目标元素的矩形区域的信息intersectionRect
:目标元素与视口(或根元素)的交叉区域的信息intersectionRatio
:目标元素的可见比例,即intersectionRect
占boundingClientRect
的比例,完全可见时为 1,完全不可见时小于等于 0。
1 |
|
option参数
参数 option
可设置 threshold
属性、root
属性,rootMargin
属性。
其中 threshold
属性决定了什么时候触发回调函数。它是一个数组,默认为 [0]
。
例 threshold = [0, 0.25]
表示当目标元素与可视区域的交叉区域分别达到 0%、25%
时触发回调函数。
另外 root
和 rootMargin
属性,root
属性指定目标元素所在的容器节点(即根元素),rootMargin
属性用来定义根元素的 margin
,用来扩展或缩小 rootBounds
这个矩形的大小,从而影响 intersectionRect
交叉区域的大小。适合目标元素在容器内滚动的场景。
方法二:
方法 Element.getBoundingClientRect()
返回元素的大小及其相对于视口的位置,这个方法返回一个名为 ClientRect的DOMRect
对象,包含了 width、height、top、bottom、left、right
的值。
我们知道 window.innerHeight
可以获得可视区域的高度,getBoundingClientRect().top
可以获取图片到可视区域顶部的距离,因此当:getBoundingClientRect().top <= window.innerHeight
时,图片在可视区域内。
判断图片是否进入可视区域
1 |
|
加载图片
页面加载时需要检查图片是否在可视区域,如果在就加载。
1 |
|