超级面板
文章目录
最新文章
最近更新
文章分类
标签列表
文章归档

Resize Observer

ResizeObserver 用于观察元素内容或边框的尺寸变化。

在这个 API 之前,都是通过 window 的 resize 事件监听元素的尺寸变化。但是这种方法不适用于这种场合:

  • 浏览器窗口大小没有变化但是元素的大小改变了的情况,比如添加删除元素隐藏元素,以及动态改变元素的大小。
  • 浏览器窗口尺寸改变了,但是元素的尺寸并没有变化,此时 resize 事件就浪费了。
    ResizeObserver 对这种场景下的使用提供了支持,而且可以替代常规的 resize 事件监听器,由于 ResizeObserver 避免了事件捕获/泡泡的开销,在性能上也会更好。

使用

从名字上看,ResizeObserver 采用了观察者模式,观察者模式在前端是一个很常用的设计模式,不再详细介绍
。使用起来也很简单:

// 创建一个观察者对象
const observer = new ResizeObserver(callback);
// 指定一个观察目标
observer.observe(target);

ResizeObserverEntry 对象

传递给 ResizeObserver 构造器回调函数 callback 中的参数是 ResizeObserverEntry 对象的集合。它有两个属性 contentRecttarget。来看一下 ResizeObserverEntry 结构:

const observer = new ResizeObserver(entries => {
entries.forEach(entry => {
console.log(entry);
});
});

observer.observe(document.body);

可以看到输出:

ResizeObserverEntry 结构

接口定义

下面列出了 ResizeObserver 的详细定义:

interface ResizeObserver {
constructor(ResizeObserverCallback callback);
void observe(Element target);// 观察一个指定的元素
void unobserve(Element target); // 取消观察一个指定的元素
void disconnect(); // 取消观察所有指定的元素
};

触发条件

W3C 规范指定了 ResizeObserver 的触发条件:

  • 当被观察的元素从 DOM 中插入或移除时,将会触发;
  • 当被观察的元素可见或不可见时,也会触发,比如 display 属性改变为 none 或者取消 none;

以下条件下不会触发:

  • 内联元素不会触发;
  • CSS transform 也不会触发;

一些使用场景总结

适用于替代原来的 onresize 事件

比如监听 textarea 大小的改变:

const initContentRect = null;
const observer = new ResizeObserver(function (entries) {
const entry = entries[0];
const contentRect = entry.contentRect;
if (!initContentRect) {
initContentRect = contentRect;
return;
}
console.log(`width changed: ${contentRect.width - initContentRect.width}, height changed: ${contentRect.height - initContentRect.height}`)
});

observer.observe(textareaEle);

感知元素的可见性

元素的 display 属性改变也会触发 ResizeObserver 的可见性,因此也可以被用来感知元素是否被使用 display: none 隐藏。

const observer = new ResizeObserver(function(entries) {
const ele = entries[0];
if (getComputedStyle(ele).display == 'none') {
console.log('隐藏');
} else {
console.log('显示');
}
});

observer.observe(ele);

兼容性

接下来看一下浏览器兼容性:

Data on support for the resizeobserver feature across the major browsers from caniuse.com

从上面可以看出来,浏览器兼容性支持度还可以,而且还有基于 MutationObserver API 实现的 polyfill

更多文档