ECMAScript 2016(ES7)引入的五个Observer API介绍

224 阅读8分钟

五种 Observers 概述

  • ResizeObserver:用于监测元素尺寸变化。
  • MutationObserver:用于监测 DOM 树的变化。
  • ReportingObserver:用于监测报告类型的变化。
  • PerformanceObserver:用于监测页面性能指标。
  • IntersectionObserver:用于监测元素是否进入视口或与其交叉。

ResizeObserver API 的使用

当使用 ResizeObserver API 时,以下是几个不同的示例,详细说明其用法并附上相应的注释:

  1. 示例:监测单个元素尺寸变化
const observer = new ResizeObserver(function (entries, observer) {
  for (let entry of entries) {
    console.log("目标元素尺寸发生变化", entry.target);
    const { width, height } = entry.contentRect;
    console.log("新的宽度:", width);
    console.log("新的高度:", height);
  }
});

const targetElement = document.getElementById("target");
observer.observe(targetElement);

这个示例中,我们使用 ResizeObserver 监测单个元素(id 为 "target")的尺寸变化。每当元素的尺寸发生变化时,回调函数将被触发,并打印出新的宽度和高度。

  1. 示例:监测多个元素尺寸变化
const observer = new ResizeObserver(function (entries, observer) {
  for (let entry of entries) {
    console.log("目标元素尺寸发生变化", entry.target);
    const { width, height } = entry.contentRect;
    console.log("新的宽度:", width);
    console.log("新的高度:", height);
  }
});

const targetElements = document.querySelectorAll(".resize-target");
targetElements.forEach((element) => {
  observer.observe(element);
});

在这个示例中,我们使用 ResizeObserver 监测多个元素(类名为 "resize-target" 的元素集合)的尺寸变化。通过使用 querySelectorAll 获取元素集合,然后遍历并对每个元素调用 observe 方法,实现对多个元素的尺寸变化进行观察。

  1. 示例:添加防抖处理
const observer = new ResizeObserver(function (entries, observer) {
  debounce(handleResize, 200); // 防抖处理回调函数

  function handleResize() {
    for (let entry of entries) {
      console.log("目标元素尺寸发生变化", entry.target);
      const { width, height } = entry.contentRect;
      console.log("新的宽度:", width);
      console.log("新的高度:", height);
    }
  }
});

const targetElement = document.getElementById("target");
observer.observe(targetElement);

function debounce(func, delay) {
  let timerId;
  return function () {
    clearTimeout(timerId);
    timerId = setTimeout(func, delay);
  };
}

在这个示例中,我们在 ResizeObserver 的回调函数中添加了防抖处理。通过调用 debounce 函数将 handleResize 函数包装成防抖函数,在元素尺寸变化时只会执行一次回调函数,并在最后一个延迟时间后触发。

请注意,以上示例仅涵盖了 ResizeObserver 的基本用法和一些扩展应用。你可以根据具体的需求进行相应的调整和扩展,例如自定义回调函数、处理其他样式属性等。

MutationObserver API 的使用

当使用 MutationObserver API 时,以下是几个不同的示例,详细说明其用法并附上相应的注释:

  1. 示例:监测单个元素的子节点变化
// 创建一个 MutationObserver 实例,并指定回调函数
const observer = new MutationObserver(function (mutationsList, observer) {
  for (let mutation of mutationsList) {
    if (mutation.type === "childList") {
      console.log("子节点发生变化");
      console.log("新增的子节点:", mutation.addedNodes);
      console.log("移除的子节点:", mutation.removedNodes);
    }
  }
});

// 开始观察目标节点
const targetNode = document.getElementById("target");
const config = { childList: true };
observer.observe(targetNode, config);

// 停止观察目标节点
observer.disconnect();

这个示例中,我们创建了一个 MutationObserver 实例来监测单个元素(id 为 "target")的子节点变化。每当子节点发生变化时,回调函数将被触发,并打印出新增和移除的子节点。

  1. 示例:监测多个元素的属性变化
const observer = new MutationObserver(function (mutationsList, observer) {
  for (let mutation of mutationsList) {
    if (mutation.type === "attributes") {
      console.log("属性发生变化");
      console.log("发生变化的元素:", mutation.target);
      console.log(
        "修改后的属性值:",
        mutation.target.getAttribute(mutation.attributeName)
      );
    }
  }
});

const targetElements = document.querySelectorAll(".observe-attribute");
targetElements.forEach((element) => {
  observer.observe(element, { attributes: true });
});

在这个示例中,我们使用 MutationObserver 监测多个元素(类名为 "observe-attribute" 的元素集合)的属性变化。通过使用 querySelectorAll 获取元素集合,然后遍历并对每个元素调用 observe 方法,实现对多个元素的属性变化进行观察。

  1. 示例:监测整个文档的变化
const observer = new MutationObserver(function (mutationsList, observer) {
  for (let mutation of mutationsList) {
    console.log("文档发生变化");
    console.log("类型:", mutation.type);
    console.log("目标节点:", mutation.target);
  }
});

observer.observe(document, { childList: true, subtree: true });

// 停止观察整个文档
observer.disconnect();

在这个示例中,我们创建了一个 MutationObserver 实例来监测整个文档的变化。通过调用 observe 方法并传入 document 对象作为目标节点,以及配置选项 { childList: true, subtree: true },实现对整个文档的子节点变化进行观察。

请注意,以上示例仅涵盖了 MutationObserver 的基本用法和一些扩展应用。你可以根据具体的需求进行相应的调整和扩展,例如监测特定属性的变化、处理其他类型的 DOM 变化等。

ReportingObserver API 的使用

当使用 ReportingObserver API 时,以下是几个不同的示例,详细说明其用法并附上相应的注释:

  1. 示例:监测页面中的错误报告
// 创建一个 ReportingObserver 实例,并指定回调函数
const observer = new ReportingObserver(function (reports, observer) {
  for (let report of reports) {
    if (report.type === "error") {
      console.log("捕获到错误报告");
      console.log("错误消息:", report.body.message);
      console.log("错误堆栈:", report.body.stack);
    }
  }
});

// 开始观察错误报告
const options = { types: ["error"] };
observer.observe(options);

// 停止观察错误报告
observer.disconnect();

这个示例中,我们创建了一个 ReportingObserver 实例来监测页面中的错误报告。每当捕获到错误报告时,回调函数将被触发,并打印出错误消息和错误堆栈信息。

  1. 示例:监测页面中的崩溃报告
const observer = new ReportingObserver(function (reports, observer) {
  for (let report of reports) {
    if (report.type === "crash") {
      console.log("捕获到崩溃报告");
      console.log("URL:", report.url);
      console.log("错误消息:", report.body.message);
    }
  }
});

const options = { types: ["crash"] };
observer.observe(options);

在这个示例中,我们使用 ReportingObserver 监测页面中的崩溃报告。当捕获到崩溃报告时,回调函数将被触发,并打印出报告的 URL 和错误消息。

  1. 示例:监测页面中的性能指标报告
const observer = new ReportingObserver(function (reports, observer) {
  for (let report of reports) {
    if (report.type === "metric") {
      console.log("捕获到性能指标报告");
      console.log("指标名称:", report.name);
      console.log("指标值:", report.body.value);
    }
  }
});

const options = { types: ["metric"] };
observer.observe(options);

在这个示例中,我们使用 ReportingObserver 监测页面中的性能指标报告。当捕获到性能指标报告时,回调函数将被触发,并打印出指标的名称和值。

请注意,以上示例仅涵盖了 ReportingObserver 的基本用法和一些扩展应用。你可以根据具体的需求进行相应的调整和扩展,例如监测其他类型的报告、处理报告数据等。

PerformanceObserver API 的使用

当使用 PerformanceObserver API 时,以下是几个不同的示例,详细说明其用法并附上相应的注释:

  1. 示例:监测页面加载性能指标
// 创建一个 PerformanceObserver 实例,并指定回调函数
const observer = new PerformanceObserver(function (list, observer) {
  for (let entry of list.getEntries()) {
    console.log("性能指标:", entry.name);
    console.log("耗时:", entry.duration);
  }
});

// 开始观察页面加载性能指标
observer.observe({ entryTypes: ["navigation"] });

// 停止观察页面加载性能指标
observer.disconnect();

这个示例中,我们创建了一个 PerformanceObserver 实例来监测页面加载性能指标。每当有新的性能指标可用时,回调函数将被触发,并打印出指标的名称和耗时。

  1. 示例:监测资源加载性能指标
const observer = new PerformanceObserver(function (list, observer) {
  for (let entry of list.getEntries()) {
    console.log("资源类型:", entry.initiatorType);
    console.log("资源名称:", entry.name);
    console.log("耗时:", entry.duration);
  }
});

observer.observe({ entryTypes: ["resource"] });

在这个示例中,我们使用 PerformanceObserver 监测资源加载性能指标。每当有新的资源加载性能指标可用时,回调函数将被触发,并打印出资源的类型、名称和耗时。

  1. 示例:监测用户交互性能指标
const observer = new PerformanceObserver(function (list, observer) {
  for (let entry of list.getEntries()) {
    console.log("用户交互类型:", entry.entryType);
    console.log("耗时:", entry.duration);
  }
});

observer.observe({ type: "first-input", buffered: true });

在这个示例中,我们使用 PerformanceObserver 监测用户交互性能指标。每当有新的用户交互性能指标可用时,回调函数将被触发,并打印出交互类型和耗时。

请注意,以上示例仅涵盖了 PerformanceObserver 的基本用法和一些常见的监测场景。你可以根据具体的需求进行相应的调整和扩展,例如监测其他类型的性能指标、处理更多的性能数据等。

IntersectionObserver API 的使用

当使用 IntersectionObserver API 时,以下是几个不同的示例,详细说明其用法并附上相应的注释:

  1. 示例:判断元素是否进入视口
// 创建一个 IntersectionObserver 实例,并指定回调函数
const observer = new IntersectionObserver(function (entries, observer) {
  for (let entry of entries) {
    if (entry.isIntersecting) {
      console.log("元素进入视口");
    } else {
      console.log("元素离开视口");
    }
  }
});

// 开始观察目标元素
const targetElement = document.getElementById("target");
observer.observe(targetElement);

// 停止观察目标元素
observer.unobserve(targetElement);

这个示例中,我们创建了一个 IntersectionObserver 实例来判断目标元素(id 为 "target" 的元素)是否进入视口。每当目标元素进入或离开视口时,回调函数将被触发,并打印出相应的信息。

  1. 示例:观察多个元素的交叉状态
const observer = new IntersectionObserver(function (entries, observer) {
  for (let entry of entries) {
    if (entry.isIntersecting) {
      console.log("元素进入视口:", entry.target);
    } else {
      console.log("元素离开视口:", entry.target);
    }
  }
});

const targetElements = document.querySelectorAll(".observe-intersection");
targetElements.forEach((element) => {
  observer.observe(element);
});

在这个示例中,我们使用 IntersectionObserver 监测多个元素(类名为 "observe-intersection" 的元素集合)的交叉状态。通过使用 querySelectorAll 获取元素集合,然后遍历并对每个元素调用 observe 方法,实现对多个元素的交叉状态进行观察。

  1. 示例:观察元素进入视口的百分比
const observer = new IntersectionObserver(function (entries, observer) {
  for (let entry of entries) {
    console.log("进入视口的百分比:", entry.intersectionRatio);
  }
});

const targetElement = document.getElementById("target");
observer.observe(targetElement);

在这个示例中,我们使用 IntersectionObserver 监测目标元素(id 为 "target" 的元素)进入视口的百分比。每当目标元素进入或离开视口时,回调函数将被触发,并打印出进入视口的百分比。

请注意,以上示例仅涵盖了 IntersectionObserver 的基本用法和一些常见的应用场景。你可以根据具体的需求进行相应的调整和扩展,例如设置阈值、使用根元素进行观察等。