什么是观察者?
在深入了解现代浏览器支持的观察者系列之前,让我们先了解一般的观察者是什么?
观察者是一个观察或注意到某事的程序。观察者有助于观察浏览器中发生的某些活动并做出相应的响应。

我们经常处理用 addEventListener 来添加事件监听用户的各种操作,比如:click, mousedown, drag, wheel 等(完整事件列表参考:https://developer.mozilla.org/zh-CN/docs/Web/Events) 。

现代浏览器提供了 5 种 Observer ,使用这些 Observer ,我们可以观察浏览器中发生的不同类型的活动,并采取必要的行动。例如。我们可以观察到,视频是否显示在视口中并启用自动播放,是否已从父 DOM 元素中添加或删除子元素,是否更改了框元素的大小 / 尺寸等等。

以下是现代浏览器支持的五种不同类型的 Observer 。

  1. Intersection Observer
  2. Mutation Observer
  3. Performance Observer
  4. Resize Observer
  5. ReportingObserver

Resize Observer
Resize Observer 允许我们观察 DOM 元素的内容矩形大小(宽度、高度)的变化并做出相应的反应。它就像元素的 document.onresize () 或 window.resize () 事件。当元素更改其大小而不调整主窗口大小时,它很有用。例如,添加新的子元素、将元素的 display 属性设置为 none 或类似的操作可以更改元素、其兄弟姐妹或祖先的大小。它只看内容框。调整大小观察者的一些行为如下所述

  • 当观察到的元素从 DOM 中插入 / 删除时,观察将触发。
  • 当观察元素显示设置为无时,观察将触发。
  • 对于未替换的内联元素,观察不会触发。
  • CSS 转换不会触发观察。
  • 如果元素有显示,并且元素的大小不是 0,0,则观察将在观察开始时触发。

调整大小观察者通知内容框的尺寸,如下图所示

** 浏览器支持:** 目前除了 chrome≥64 以外的大部分浏览器都不支持。

观察者的 api 可以作为其他观察者分三步使用
a) 创建观察者
只需调用其构造函数并传递处理函数即可创建。

const observer = new ResizeObserver(handler);

b) 定义要观察的目标对象
定义要观察其大小变化的目标对象。

const child = document.querySelector(.child”);
observer.observe(child);

c) 定义回调处理程序

function handler(entries) {
  entries.forEach((entry) => {
    const size = entry.target.contentRect;
    console.log(
      `Element’s size: width: ${size.width} , height: ${size.height}`
    );
  });
}

示例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      button {
        background: purple;
        color: white;
        cursor: pointer;
        display: inline-block;
        font-size: 20px;
        padding: 1.75rem 1rem;
        text-align: center;
        text-decoration: none;
        font-weight: bold;
        margin-right: 5px;
      }
      .box {
        box-sizing: border-box;
        margin-top: 10px;
        border: 1px solid green;
        width: 300px;
        height: 200px;
        text-align: center;
        padding: 20px;
        font-size: 25px;
      }
    </style>
  </head>
  <body>
    <button>Resize Box Below</button>
    <div class="box"></div>
    <script>
      if (!("ResizeObserver" in window)) {
        document.body.innerText = "Not supported by your browser";
      }
      /* Create resize observer */
      const observer = new ResizeObserver(handler);
      /* Callback handler */
      function handler(entries) {
        entries.forEach((entry) => {
          const size = entry.contentRect;
          console.log(
            `Resize Observer's callback: box size: width: ${size.width} , height:  ${size.height}`
          );
        });
      }
      /* Observe child element */
      const child = document.querySelector(".box");
      observer.observe(child);
      // Click event listener for button
      const box = document.querySelector(".box");
      let boxWidth = box.getBoundingClientRect().width;
      let boxHeight = box.getBoundingClientRect().height;
      box.innerText = `Width: ${boxWidth} , Height: ${boxHeight}`;
      const boxSizes = [200, 300, 450, 500, 550, 600];
      document.querySelector("button").addEventListener("click", function () {
        // Select random width and height of a box element
        boxWidth = boxSizes[Math.floor(Math.random() * boxSizes.length)];
        boxHeight = boxSizes[Math.floor(Math.random() * boxSizes.length)];
        box.style.width = boxWidth + "px";
        box.style.height = boxHeight + "px";
        box.innerText = `Width: ${boxWidth} , Height: ${boxHeight}`;
      });
    </script>
  </body>
</html>