最近看到一个手写图片懒加载的文章,里面用了两种方法,一种是大家都很熟悉的onScroll事件,另一种就是IntersectionObserver这个API,然后我查了一下感觉还是很有用的,所以记录一下。

Intersection Observer API

Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。简单来说,这个API就是用来检测目标元素与其父级或祖先元素或者视口是否接触。在以前我们需要监听元素的OnScroll事件然后在方法中调用 Element.getBoundingClientRect()方法来获取元素相对视口左上角的坐标,然后再计算判断是否在视口之内。毫无疑问这种方式带来的数据量和计算量是巨大的,虽然对于现在的处理器来说小菜一碟但是难免不保证在老机型或者多应用的情况下会出现卡顿的情况,这个时候使用Intersection ObserverAPI就会方便很多。

一、使用方法

创建一个 IntersectionObserver 对象,并传入相应参数和回调用函数,该回调函数将会在目标(target)元素和根(root)元素的交集大小超过阈值(threshold)规定的大小时候被执行,options是配置对象(该参数可选)。
阈值为1.0意味着目标元素完全出现在 root 选项指定的元素中可见时,回调函数将会被执行。

let options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 1.0
}

let observer = new IntersectionObserver(callback, options);

构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。

// 开始观察
observer.observe(document.getElementById('example'));

// 停止观察
observer.unobserve(element);

// 关闭观察器
observer.disconnect();

如果要观察多个节点,就要多次调用这个方法。

observer.observe(elementA);
observer.observe(elementB);

二、options参数

  1. root
    指定根(root)元素,用于检查目标的可见性。必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。

  2. rootMargin
    根(root)元素的外边距。类似于 CSS 中的 margin 属性,比如 “10px 20px 30px 40px” (top, right, bottom, left)。如果有指定 root 参数,则 rootMargin 也可以使用百分比来取值。该属性值是用作 root 元素和 target 发生交集时候的计算交集的区域范围,使用该属性可以控制 root 元素每一边的收缩或者扩张。默认值为0。

  3. threshold
    可以是单一的 number 也可以是 number 数组,target 元素和 root 元素相交程度达到该值的时候 IntersectionObserver 注册的回调函数将会被执行。如果你只是想要探测当 target 元素的在 root 元素中的可见性超过50%的时候,你可以指定该属性值为0.5。如果你想要 target 元素在 root 元素的可见程度每多25%就执行一次回调,那么你可以指定一个数组 [0, 0.25, 0.5, 0.75, 1]。默认值是0 (意味着只要有一个 target 像素出现在 root 元素中,回调函数将会被执行)。该值为1.0含义是当 target 完全出现在 root 元素中时候 回调才会被执行。

三、callback参数

callback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。
callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象
回调接收 IntersectionObserverEntry 对象和观察者的列表:

let callback =(entries, observer) => {
  entries.forEach(entry => {
    // Each entry describes an intersection change for one observed target element:
    // entry.boundingClientRect
    // entry.intersectionRatio
    // entry.intersectionRect
    // entry.isIntersecting
    // entry.rootBounds
    // entry.target
    // entry.time
  });
};

四、IntersectionObserverEntry 对象

IntersectionObserverEntry对象提供目标元素的信息,一共有六个属性。

{
  time: 3893.92,
  rootBounds: ClientRect {
    bottom: 920,
    height: 1024,
    left: 0,
    right: 1024,
    top: 0,
    width: 920
  },
  boundingClientRect: ClientRect {
     // ...
  },
  intersectionRect: ClientRect {
    // ...
  },
  intersectionRatio: 0.54,
  target: element
}

每个属性含义如下:

  • time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
  • target:被观察的目标元素,是一个 DOM 节点对象
  • rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
  • boundingClientRect:目标元素的矩形区域的信息
  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息
  • intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0

五、参考链接

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐