过去,要检测一个元素是否可见或者两个元素是否相交并不容易,比如实现图片懒加载、内容无限滚动等功能时,都需要通过​getBoundingClientRect()​写大量的逻辑计算或者依靠scroll事件监听等性能很差方式来实现。

现在,依靠IntersectionObserver我们能非常便捷且高效的实现上述功能。

一、API

// 创建实例
const observer = new IntersectionObserver(callback, option);
// 开始观察element1
observer.observe(element1);
// 开始观察element2
observer.observe(element2);
// 停止观察
observer.unobserve(element);
// 关闭观察器
observer.disconnect();

IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。

构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点,如果需要观察多个DOM节点可以多次添加observe方法。

二、callback 参数

当以下情况发生时会调用回调函数:

IntersectionObserver API详解  

callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员。

每个IntersectionObserverEntry对象属性含义如下:

三、Option 对象

IntersectionObserver构造函数的第二个参数是一个配置对象。它可以设置以下属性。

 四、注意点

五、实例:无限滚动

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>IntersectionObserver</title>
</head>
<body style="font-size: 24px;text-align: center">
<div id="container"></div>
<div id="loadMore">加载中...</div>
</body>
<script>
  const container = document.querySelector('#container');
  const loadMore = document.querySelector('#loadMore');
  let index = 0;
  const loadItems = (count) => {
    [...Array(count).keys()].forEach((key) => {
      const p = document.createElement('P');
      p.innerHTML = `${key + index}`;
      container.appendChild(p)
    })
    index += count;
  }
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(({ isIntersecting }) => {
      if (isIntersecting) {
        loadItems(20);
      }
    })
  });
  observer.observe(loadMore)
</script>
</html>

无限滚动(infinite scroll)的实现也很简单。通过观察#loadMore元素与浏览器视图的是否交叉,如果交叉则意味着列表已经加载完毕,继续添加更多的元素。

IntersectionObserver API详解

参考:

Intersection Observer API - Web API 接口参考 | MDN

IntersectionObserver API 使用教程 - 阮一峰的网络日志