如何使用 Resize Observer JavaScript API

介绍

Resize Observer是一个新的 JavaScript API,它与Intersection Observer API等其他观察者 API 非常相似它允许在元素大小发生变化时通知元素。

元素大小改变的最常见原因是当视口被调整大小或设备的方向在纵向和横向之间改变时。到目前为止,我们不得不依赖全局window.resize事件来监听调整大小事件并检查某些元素是否改变了大小。由于大量的触发事件,这很容易导致性能问题。换句话说,使用window.resize通常是浪费的,因为它会通知我们每个视口大小的变化,而不仅仅是当元素的大小实际发生变化时。

Resize Observer API 的另一个用例是窗口的 resize 事件无法帮助我们处理:当动态添加或从 DOM 中删除元素时,会影响父元素的大小。这在现代单页应用程序中越来越频繁。

在本教程中,您将了解 React Observer 的基本用法。您还将在自己的前端代码中实现 React Observer 并测试浏览器支持。

先决条件

要成功完成本教程,您需要具备以下条件:

步骤 1 — 了解 Resize Observe 的基本用法

使用 Resize Observer 是通过实例化一个新ResizeObserver对象并传入接收观察到的条目的回调函数来完成的:

const myObserver = new ResizeObserver(entries => {

});

在回调函数中,您可以遍历条目。ResizeObserver实例化后,实例observe上调用函数并传入要观察的元素:

const someEl = document.querySelector('.some-element');
const someOtherEl = document.querySelector('.some-other-element');

myObserver.observe(someEl);
myObserver.observe(someOtherEl);

每个条目都分配了一个带有contentRecttarget属性的对象target是DOM元素本身,并且contentRect是具有以下属性的对象:宽度,高度,X,Y,上,右,下和左。

与元素的 不同,宽度和高度getBoundingClientRectcontentRect值不包括填充值。contentRect.top是元素的顶部填充,contentRect.left是元素的左填充。

例如,如果您想在元素大小更改时记录观察元素的宽度和高度,请首先创建一个名为的常量变量myObserver并实例化一个 new ResizeObserver

const myObserver = new ResizeObserver(entries => {

});

在回调函数内部,使用forEach以下命令遍历每个条目

const myObserver = new ResizeObserver(entries => {
  entries.forEach(entry => {

  });
});

forEach循环中,console.log每个条目的宽度和高度分别使用entry.contentRect.widthentry.contentRect.height

const myObserver = new ResizeObserver(entries => {
  entries.forEach(entry => {
    console.log('width', entry.contentRect.width);
    console.log('height', entry.contentRect.height);
  });
});

myObserver使用,请创建一个someEl使用 DOM 选择器调用的元素通过在someEl作为参数myObserver.observe

const myObserver = new ResizeObserver(entries => {
  entries.forEach(entry => {
    console.log('width', entry.contentRect.width);
    console.log('height', entry.contentRect.height);
  });
});

const someEl = document.querySelector('.some-element');
myObserver.observe(someEl);

了解如何使用 Resize Observer 后,您现在可以继续将 Resize Observer 用于实际用例。

步骤 2 — 演示如何使用 Resize Observer

下面是查看 Resize Observer API 实际操作的演示。通过调整浏览器窗口的大小来尝试一下,注意渐变角度和文本内容仅在元素大小实际受到影响时才发生变化:

在使用 Resize Observer API 之前,您首先需要创建一个index.html文件:

  • touch index.html

在 HTML 文件中,添加以下代码:

索引.html
<div class="box">
  <h3 class="info"></h3>
</div>
<div class="box small">
  <h3 class="info"></h3>
</div>

您还需要向 HTML 添加一些样式。创建一个styles.css文件并将以下 CSS 代码添加到该文件中:

样式文件
.box {
  text-align: center;
  height: 20vh;
  border-radius: 8px;
  box-shadow: 0 0 4px var(--subtle);

  display: flex;
  justify-content: center;
  align-items: center;
}

.box h3 {
  color: #fff;
  margin: 0;
  font-size: 5vmin;
  text-shadow: 0 0 10px rgba(0,0,0,0.4);
}

.box.small {
  max-width: 550px;
  margin: 1rem auto;
}

注意渐变背景不需要应用于.box元素。当页面第一次加载时,调整大小观察器将被调用一次,然后将应用渐变。

现在,是时候转到 JavaScript 代码了。您可以创建外部 JavaScript 文件,也可以<script>向 HTML 文件中添加标签。首先,为所有.box元素创建一个 DOM 选择器

const boxes = document.querySelectorAll('.box');

现在ResizeObserver使用一个回调函数实例化一个 new函数,该函数接受一个名为 的参数entries

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {

});

创建一个for...of循环来遍历每个entryin entries在循环内,创建一个infoEl设置为等于的常量变量entry.target.querySelector('.info')这指向.info元素为target

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
  }
});

创建常量变量widthheight将分别设置为entry.contentRect.widthentry.contentRect.height应用于Math.floor两者以向下取整值:

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);
  }
});

由于您将以随屏幕宽度变化的角度创建渐变,因此创建一个angle将设置为等于变量width / 360 * 100同样,使用Math.floor向下舍入此值:

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);

    const angle = Math.floor(width / 360 * 100);
  }
});

创建一个名为的常量gradient,用于保存线性渐变的代码:

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);

    const angle = Math.floor(width / 360 * 100);
    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
  }
});

有了这个渐变,您需要将目标条目的背景设置为gradientusing entry.target.style.background

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);

    const angle = Math.floor(width / 360 * 100);
    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;

    entry.target.style.background = gradient;
  }
});

这将是有益的,看看对价值观widthheight画面的变化上。innerTextofinfoEl并将其设置为I'm ${width}px and ${height}px tall

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);

    const angle = Math.floor(width / 360 * 100);
    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;

    entry.target.style.background = gradient;

    infoEl.innerText = `I'm ${width}px and ${height}px tall`;
  }
});

的回调ResizeObserver完成。现在该myObserver函数可以应用于boxes使用forEach循环:

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);

    const angle = Math.floor(width / 360 * 100);
    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;

    entry.target.style.background = gradient;

    infoEl.innerText = `I'm ${width}px and ${height}px tall`;
  }
});

boxes.forEach(box => {
  myObserver.observe(box);
});

请注意您还必须如何迭代可以观察和调用observe每个元素的元素。

这是一个如何使用 Resize Observer 进行响应式设计的工作示例。但是,重要的是要注意浏览器对此类 JavaScript 功能的支持。

第 3 步 – 评估浏览器支持

目前浏览器对 Resize Observer 的支持不是很广泛。幸运的是,有一个 polyfill可以同时使用。polyfill 基于MutationObserver API

您可以访问我可以使用 resizeobserver 吗?跟踪主要浏览器对此功能的支持。

结论

在本教程中,您能够了解 Reserve Observer 可以做什么,在您的 JavaScript 代码中使用它,并测试浏览器支持。

对于接下来的步骤,您可能有兴趣学习如何使用ReactVue等 JavaScript 框架处理响应式设计

觉得文章有用?

点个广告表达一下你的爱意吧 !😁