# ResizeObserver监听元素的resize事件

最近在写业务中有遇到需要监听一个元素resize事件的需求(为了实现自适应布局)。

虽然存在window.onresize这个API,但是它却是用来监听浏览器窗口resize事件,那我在业务中总不能让用户去拖拽浏览器窗口吧,这听着就不是一个好主意。


几经查找(百度),发现了ResizeObserver,虽然该API目前还处在实验中,但是浏览器兼容性非常不错:👇

resize-observer-01

有鉴于我司产品只应用于PC端浏览器,不用考虑兼容移动端,而且貌似也没有其它的解决办法,所以姑且用它把。。

ResizeObserver的API:👇

方法 介绍
ResizeObserver.disconnct() 取消和结束目标对象上所有对ElementSVGElement观察。
ResizeObserver.observe() 开始观察指定的ElementSVGElement
ResizeObserver.unobserve() 结束观察指定的ElementSVGElement

# 一、使用

# 创建一个ResizeObserver

const ro = new ResizeObserver(res => {
  console.log(res);// 看一下返回的东西
})

ro.observe(document.getElementById("xxx"));
1
2
3
4
5

resize-observer-02

返回的是一个数组,它里面最重要的就两个属性:contentRecttargettarget就不说了,就是当前监听的DOM节点contentRect则包含了这个DOM节点的参数,包括width、height、bottom、left、right、top、x和y,这些应该足够使用了。

# 取消/暂时结束观察

ro.disconnct();
1

一般写在监听DOM节点被隐藏时(可以结合业务判断),主要目的是为了在隐藏/不再显示这段时间内暂时取消监听,节省开销。

那么在重新打开/进入模块时还需要重新监听:

if (ro) ro.observe();
1

# 终止观察

ro.unobserve();
1

模块销毁时彻底结束观察。

# 二、需要注意的

参考资料[1]中说了:

...在使用ResizeObserver API的时候,在每次触发元素的大小变化时,会在1s内触发回调蛮多次的。如果想进一步优化性能,可以加上throttle节流函数处理...

这里节流的话,在业务中实际使用会发现效果并不会流畅,就是会是一顿一顿的

因为节流实际上把多个事件只取一个进行处理(并不是合并,也不会合并),比如监听返回了30个事件,但却回调只执行了6次。

虽然是节省了开销,防止连续触发回调事件,但是如果回调的方法是执行动画效果的话,就不会很连贯,这样的话可能还需要配合transition这个CSS样式才行。

# 三、参考资料

Last Updated: 2 years ago