1

IntersectionObserver

介绍

IntersectionObserver 翻译为 "交叉观察者"。提供了一种异步观察目标元素与其祖先元素(默认是顶级文档视窗)交叉状态的方法,祖先元素被称为根(root)。

1、IntersectionObserver 是异步的,不随着目标元素的滚动同步触发。底层应该是采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。

2、必须是子元素跟祖先元素发生交叉。

语法

1、构造函数

const io = new IntersectionObserver(cb,options);

2、回调函数
发生交叉的回调,接受一个entries参数,是一个数组,返回当前已监听并且发生了交叉的目标集合

new IntersectionObserver(entries => {
  entries.forEach(entry => console.log(entry));
  // ...
});

我们看看entry里面包含哪些常用属性:

属性 说明
target 目标元素
rootBounds 根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
boundingClientRect 目标元素的矩形区域的信息
intersectionRect 目标元素与视口(或根元素)的交叉区域的信息
intersectionRatio 目标元素可见区域的占比,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0
isIntersecting 字面理解为是否正在交叉,可用做判断目标元素是否可见,为true时,目标元素从不可见到可见,为false时,目标元素从可见到不可见。

3、options
顾名思义,它是一个配置参数,对象类型,非必填,有3个属性如下:

属性 说明
root 指定祖先元素,默认为视窗
rootMargin 触发交叉的偏移值,默认为"0px 0px 0px 0px"(上左下右,正数为向外扩散,负数则向内收缩)
threshold 该属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个阈值,如[0, 0.25, 0.5, 0.75, 1],默认为[0]

4、实例方法

属性 说明 参数
observe 开始监听一个目标元素 节点
unobserve 停止监听一个目标元素 节点
takeRecords 返回所有监听的目标元素集合
disconnect 停止所有监听

实例

图片懒加载

lazyload

  <div class="parent">
    <div>
      <img class="child" data-origin="some-real-url.jpg" />
    </div>
    ...
  </div>
  let parent = document.querySelector(".parent");
  let childs = document.querySelectorAll(".child");

  let observer = new IntersectionObserver(entries => {
    entries.forEach(item => {
      if (item.isIntersecting) {
        item.target.src = item.target.dataset.origin; // 开始加载图片
        observer.unobserve(item.target); // 停止监听已开始加载的图片
      }
    });
  }, {
    root: parent,
  });

  childs.forEach(item => { observer.observe(item); });

动画展示

动画
相信很多人都需要过这种需求,当某个元素出现的时候就给该元素加个动画,比如渐变、偏移等;

<ul>
  <li></li> // 多个li
</ul>
li.show {
  /* 默认从左边进来 */
  animation: left 1s ease;
}

li.show:nth-child(2n) {
  /* 偶数从右边进来 */
  animation: right 1s ease;
}

@keyframes left {
  from {
    opacity: 0;
    transform: translate(-20px, 20px);
  }

  to {
    opacity: 1;
  }
}

@keyframes right {
  from {
    opacity: 0;
    transform: translate(20px, 20px);
  }

  to {
    opacity: 1;
  }
}
let list = document.querySelectorAll("ul li");

let observer = new IntersectionObserver(entries => {
  entries.forEach(item => {
    if (item.isIntersecting) {
      item.target.classList.add("show"); // 增加show类名
      observer.unobserve(item.target); // 移除监听
    }
  });
});

list.forEach(item => observer.observe(item));

浏览器兼容性

IE不兼容,不过有官方的polyfill,链接地址为:polyfill

MutationObserver

ResizeObserver

PerformanceObserver

参考资料
现代浏览器支持的不同类型的观察者
轻轻松松实现高难度懒加载、吸顶、触底
IntersectionObserver API 使用教程


Cris
42 声望1 粉丝