令我有点惊讶的是,为了监听元素尺寸(而不是窗口对象)的变化,我们必须使用一个名为
ResizeObserver
的新接口。虽然它看起来做得很好;这似乎与其他元素相关事件有点不同,只需添加一个侦听器即可使用这些事件。
以添加事件监听器为例,监听mouseover事件
document.querySelector('#ele').addEventListener('mouseover', callback);
为什么不简单地为元素上的调整大小事件添加一个新的监听器?
document.querySelector('#ele').addEventListener('resize', callback);
是为了避免与window
resize
事件冲突吗?如果是这样,为什么不换个方式称呼它呢
document.querySelector('#ele').addEventListener('elementResize', callback);
我知道创建一个辅助方法来简化
ResizeObserver
的使用很容易。类似的东西可以像原来的addEventListener
方法一样简单使用
export const getResizeObserver = ( ele, onResize ) => {
let obs;
const observerInterface = {
stop: () => { obs.unobserve( ele ); obs.disconnect() },
};
obs = new ResizeObserver( entries => {
for ( const entry of entries ) {
onResize && onResize( entry.contentRect );
}
} );
obs.observe( ele );
return observerInterface;
};
// usage to add the listener
const obs = getResizeObserver(document.querySelector('#ele'), callback);
// later to remove the listener
obs.stop();
无论如何,除了 api 首选项和多个元素可以共享观察者实例这一事实之外,是否还有任何原因使得
ResizeObserver
方法比 addEventListener
方法更好?
在此 PR 中进行了一次讨论,其中 W3C 技术架构小组尝试定义何时在 EventTarget 上使用观察者模式。这次讨论的结果记录在here,我引用第一个陈述:
一般来说,使用EventTarget和通知事件,而不是 观察者模式,除非 EventTarget 不能很好地适合您 特点。使用观察者模式相对于
EventTarget的优点如下:
具体谈谈
- 可以在观察时或创建时自定义实例。观察者的构造函数或其
observe()
方法可以采用选项,允许作者自定义每个回调的观察内容。这对于addEventListener()
来说是不可能的。- 使用 Observer 对象上的
disconnect()
或unobserve()
方法可以轻松停止监听多个回调。- 您可以选择提供像
takeRecords()
这样的方法,它会立即获取相关数据,而不是等待事件触发。- 因为观察者是单一用途的,所以您不需要指定事件类型。
ResizeObserver
,我认为:
resize
事件在这里会是一个更好的匹配。
takeRecords()
方法,所以3d点不相关
Event 模型。
此外,还可能存在性能问题或不可避免的递归,但我没有找到任何有关它们的测量或解释。
提出的,但 Chrome 决定使用观察者模型来发布它,似乎主要是因为它比基于事件的实现快 10 倍https://groups.google.com/a/chromium.org/forum/ #!topic/blink-dev/z6ienONUb5A
现在为什么确实如此,我不知道。