在以前如果我们想要监听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