 
  图片懒加载原理
欢迎阅读,本文将介绍图片懒加载的两种方式。
前言
目前项目中需要加载的图片很多,我们知道服务器请求次数过多,势必会影响到性能。为提高网页性能,需要实现图片的“按需加载”(图片懒加载),即图片默认暂时不加载,当图片即将进入可视区域时,再进行加载。
原理
当 <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()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
- boundingClientRect:目标元素的矩形区域的信息
- 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 |  |