在以前如果我们想要监听dom
元素的大小变化,我们是没有对应的api
可以使用的,在此之前我们都是只能监听浏览器窗口的大小变化,于是衍生出很多的hack
方法,比如resize
事件,scroll
事件,requestAnimationFrame
等等,但是这些方法都有一些缺点,比如resize
事件会频繁触发,scroll
事件会频繁触发,requestAnimationFrame
会频繁触发,而且这些方法都是监听window
的变化,而不是dom
元素的变化,所以我们需要一个api
来监听dom
元素的大小变化,于是ResizeObserver
就应运而生了。
1. ResizeObserver
ResizeObserver
作为一个标准的web``api
,它的作用是监听dom
元素的大小变化,它的api
非常简单,只有一个observe
方法,它接受一个dom
元素作为参数,然后就可以监听这个dom
元素的大小变化了,当然,我们也可以使用unobserve
方法来停止监听这个dom
元素的大小变化。
我们先来看一下ResizeObserver
的函数签名:
interface ResizeObserver {
constructor(callback: ResizeObserverCallback): void;
observe(target: Element): void;
unobserve(target: Element): void;
disconnect(): void;
}
interface ResizeObserverCallback {
(entries: ResizeObserverEntry[], observer: ResizeObserver): void;
}
ResizeObserver
是一个web
标准的api
,所以我们可以放心的使用它,它的作用是监听dom
元素的大小变化,它的使用方法如下:
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const {
width, height } = entry.contentRect;
console.log(`Element: ${
entry.target}`);
console.log(`Element size: ${width}px x ${height}px`);
console.log(`Element padding: ${
entry.paddingBoxSize}`);
}
});
resizeObserver.observe(document.querySelector('.resize'));
上面的代码中,我们创建了一个ResizeObserver
实例,然后调用observe
方法来监听dom
元素的大小变化,当dom
元素的大小发生变化的时候,ResizeObserver
实例会触发回调函数,回调函数的参数是一个entries
数组,数组中的每一项都是一个ResizeObserverEntry
对象,它包含了dom
元素的大小信息,我们可以通过contentRect
属性来获取dom
元素的大小信息,它是一个DOMRectReadOnly
对象,它包含了dom
元素的大小信息,我们可以通过width
和height
属性来获取dom
元素的宽度和高度,我们也可以通过paddingBoxSize
属性来获取dom
元素的padding
的大小。
2. ResizeObserverEntry
上面的关键点在于回调函数中的entries
参数,它是一个ResizeObserverEntry
对象的数组,我们可以通过它来获取dom
元素的大小信息。
ResizeObserverEntry
对象包含了dom
元素的大小信息,它的属性如下:
borderBoxSize
:dom
元素的border
的大小。contentBoxSize
:dom
元素的content
的大小。contentRect
:dom
元素的大小信息,它是一个DOMRectReadOnly
对象,它包含了dom
元素的大小信息,我们可以通过width
和height
属性来获取dom
元素的宽度和高度,我们也可以通过paddingBoxSize
属性来获取dom
元素的padding
的大小。devicePixelContentBoxSize
:dom
元素的devicePixelContent
的大小。target
:dom
元素。time
:dom
元素大小变化的时间。transformBox
:dom
元素的transform
的大小。x
:dom
元素的x
轴的大小。y
:dom
元素的y
轴的大小。constructor
:ResizeObserverEntry
对象的构造函数。isBoxSizeSynced
:dom
元素的大小是否同步。
浏览器兼容性
作为一个新兴的api
,ResizeObserver
的兼容性还不是很好,目前只有Chrome
和Firefox
支持它,Safari
和Edge
还不支持,所以我们在使用的时候需要注意一下。
ResizeObserver
的兼容性如下:
- Chrome:
v64
及以上。 - Firefox:
v63
及以上。 - Safari:
v13
及以上。 - Edge:
v79
及以上。 - Opera:
v51
及以上。
可以去caniuse查看更多的兼容性信息。
总结
ResizeObserver
解决了我们没用监听dom
大小变化的难题,作为新一代的标准api
,它的兼容性虽然还不是很好,但是还是可以添加polyfill
来解决兼容性的问题,所以我们可以放心的使用它。
最后使用之后记得清除ResizeObserver
对象,否则会造成内存泄漏。
参考:https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver