Skip to main content

ResizeObserver 监听尺寸

什么是 ResizeObserver

ResizeObserver 用于监听 DOM 元素节点增减、属性/宽高/内容的变化。相较于 window.onresize 只能获取/设置当前窗口的 resize 事件更为高效灵活。

一、基本用法

ResizeObserver 是个构造函数。需要使用 new 关键字调用,通过 observe 方法指定监听的元素。

1、通用监听

const resizeObserver = new ResizeObserver(entries => {
console.log(entries)
});
// 监听单个 DOM 元素尺寸的变化
resizeObserver.observe(document.querySelector('#box'))

当该 DOM 元素尺寸变化时输出:

可通过监听 body 节点来模拟 window.onresize

const resizeObserver = new ResizeObserver(entries => {
console.log(entries)
});
// 监听整个 body 的变化
resizeObserver.observe(document.body)

当窗口尺寸发生变化时输出:

2、只监听某一类变化

observe 的第二个参数是可选值,可指定只监听某一类变化,其中,必须有 childListattributescharacterData 中一种或多种,否则会报错。可设置的属性如下:

  • childList(布尔值),表示是否监听子节点的变动;
  • attributes(布尔值),表示是否监属性的变动;
  • characterData(布尔值),表示是否监听节点内容/文本的变动;
  • subtree(布尔值),表示是否监听所有后代节点;
  • attributeFilter(数组),表示观察特定属性;
  • attributeOldValue(布尔值),表示观察 attributes 变动时,是否需要记录变动前的属性值;
  • characterDataOldValue(布尔值),表示观察 characterData 变动,是否需要记录变动前的值;
const resizeObserver = new ResizeObserver(entries => {
console.log(entries)
});
const options = {
childList: true, // 子节点的变动(新增、删除或者更改)
attributes: true, // 属性的变动
characterData: true, // 节点内容或节点文本的变动
subtree: true, // 是否将观察器应用于该节点的所有后代节点
attributeFilter: ['class', 'style'], // 观察特定属性
attributeOldValue: true, // 观察 attributes 变动时,是否需要记录变动前的属性值
characterDataOldValue: true // 观察 characterData 变动,是否需要记录变动前的值
}
resizeObserver.observe(document.querySelector('#box'), options)

二、取消监听

removeEventListener 同理,需要取消监听。

1、取消单个 resizeObserver 监听

可通过 unobserve 取消指定节点的 resizeObserver 监听。

const resizeObserver = new ResizeObserver(entries => {
console.log(entries)
});
resizeObserver.observe(document.querySelector('#box'))

// 2s 后取消指定节点的监听
setTimeout(() => {
resizeObserver.unobserve(document.querySelector('#box'))
}, 2000)

2、取消所有 resizeObserver 监听

可通过 disconnect 取消所有节点的 resizeObserver 监听。

const resizeObserver = new ResizeObserver(entries => {
console.log(entries)
});
resizeObserver.observe(document.querySelector('#box'))
resizeObserver.observe(document.body)

// 2s 后取消所有节点的监听
setTimeout(() => {
resizeObserver.disconnect()
}, 2000)

在 React 中使用时,一般会在 useEffect 的返回值中对 ResizeObserver 统一销毁:

useEffect(() => {
const resizeObserver = new ResizeObserver(entries => {
console.log(entries)
});
resizeObserver.observe((triggerNode.current as any))
return () => resizeObserver.disconnect()
}, [])