什么是观察者?
在深入了解现代浏览器支持的观察者系列之前,让我们先了解一般的观察者是什么?
观察者是一个观察或注意到某事的程序。观察者有助于观察浏览器中发生的某些活动并做出相应的响应。
我们经常处理用 addEventListener 来添加事件监听用户的各种操作,比如:click, mousedown, drag, wheel 等(完整事件列表参考:https://developer.mozilla.org/zh-CN/docs/Web/Events) 。
现代浏览器提供了 5 种 Observer ,使用这些 Observer ,我们可以观察浏览器中发生的不同类型的活动,并采取必要的行动。例如。我们可以观察到,视频是否显示在视口中并启用自动播放,是否已从父 DOM 元素中添加或删除子元素,是否更改了框元素的大小 / 尺寸等等。
以下是现代浏览器支持的五种不同类型的 Observer 。
- Intersection Observer
- Mutation Observer
- Performance Observer
- Resize Observer
- 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> |