介绍
Resize Observer是一个新的 JavaScript API,它与Intersection Observer API等其他观察者 API 非常相似。它允许在元素大小发生变化时通知元素。
元素大小改变的最常见原因是当视口被调整大小或设备的方向在纵向和横向之间改变时。到目前为止,我们不得不依赖全局window.resize
事件来监听调整大小事件并检查某些元素是否改变了大小。由于大量的触发事件,这很容易导致性能问题。换句话说,使用window.resize
通常是浪费的,因为它会通知我们每个视口大小的变化,而不仅仅是当元素的大小实际发生变化时。
Resize Observer API 的另一个用例是窗口的 resize 事件无法帮助我们处理:当动态添加或从 DOM 中删除元素时,会影响父元素的大小。这在现代单页应用程序中越来越频繁。
在本教程中,您将了解 React Observer 的基本用法。您还将在自己的前端代码中实现 React Observer 并测试浏览器支持。
先决条件
要成功完成本教程,您需要具备以下条件:
- 对 HTML 的理解。该如何建立与HTML系列网站是一个伟大的地方开始。
- CSS的基础知识。该如何建立一个网站使用CSS系列可以帮助你实现这一目标。
- 了解 JavaScript
for
和forEach
循环。要了解有关循环的更多信息,请访问这篇名为For Loops、For…Of Loops 和 For…In Loops in JavaScript 的文章。该文章提供了如何进行彻底的解释forEach
循环工作。 - 了解 JavaScript 中的 DOM 操作。如果您想了解有关此主题的更多信息,请访问了解 DOM — 文档对象模型系列。
步骤 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);
每个条目都分配了一个带有contentRect
和target
属性的对象。的target
是DOM元素本身,并且contentRect
是具有以下属性的对象:宽度,高度,X,Y,上,右,下和左。
与元素的 不同,宽度和高度getBoundingClientRect
的contentRect
值不包括填充值。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.width
和entry.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 文件中,添加以下代码:
<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
循环来遍历每个entry
in 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');
}
});
创建常量变量width
和height
将分别设置为entry.contentRect.width
和entry.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))`;
}
});
有了这个渐变,您需要将目标条目的背景设置为gradient
using 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;
}
});
这将是有益的,看看对价值观width
和height
画面的变化上。取innerText
ofinfoEl
并将其设置为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 代码中使用它,并测试浏览器支持。