检测DOM尺寸变化JS API ResizeObserver简介

byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9295

本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

一、关于MutationObserver提两句

DOM元素的属性或者节点变化的检测,我们可以使用MutationObserver对象,IE11+支持,具体可以参见“ 聊聊JS DOM变化的监听检测与应用 ”这篇文章。

但是如果我们想要检测到DOM元素尺寸变化,在过去是没有专门的API的,多借助window对象上绑定resize事件。

但是DOM元素的尺寸变化,有时候窗体的尺寸没有变化也会触发。还有的时候窗体的尺寸变化了,但是DOM元素的尺寸并没有变化,window对象上绑定的resize事件就有些浪费。

由于以上一些原因,一个全新的API就出来了,就是ResizeObserver对象,专门用来观察DOM元素的尺寸是否发生了变化。

这个API游览器支持的非常迅速,我记得去年看的时候才chrome浏览器支持,现在Firefox浏览器也支持了,Safari也确定会支持,估计不用多久就可以使用了。

二、ResizeObserver语法

假设页面上有个DOM元素,名叫eleZxx,则我们想要在eleZxx尺寸变化的时候做点什么事情,可以使用下面的JavaScript代码:

var ro = new ResizeObserver( entries => {
  for (let entry of entries) {
    const cr = entry.contentRect;
    console.log('Element:', entry.target);
    console.log(`Element size: ${cr.width}px x ${cr.height}px`);
    console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
  }
});

// 观察一个或多个元素
ro.observe(eleZxx);

此时我们在控制台就你呢个看到类似下图的结果:

contentRect指的是什么?

entry.contentRect 返回的是一个DOMRect对象,例如的属性包括:

{
    x: 0
    y: 0
    width: 296
    height: 100
    top: 0
    right: 296
    bottom: 100
    left: 0
}

如果我们给DOM元素设置个 padding:10px ,则宽高都会变小,同时 lefttop 属性值变成了 10

{
    x: 10
    y: 10
    width: 276
    height: 100
    top: 10
    right: 286
    bottom: 110
    left: 10
}

这表明contentRect返回是content box,也就是内容区域的尺寸。

我从Google Developers找了张content box示意图,参见下图中间那部分:

同时也从侧面说明了,如果一个元素的content box的尺寸没有发生变化,那么也是不会触发ResizeObserver观察执行的,哪怕你改变了元素的 padding 值,或者改变了元素的 border-width 边框尺寸,都不会认为是DOM元素尺寸变化了。

例如:

div {
    width: 200px; height:100px;
}

则上面这个div元素设置 padding:10px ,是没有不会触发ResizeObserver执行的。

Firefox中另外两个对象

Firefox浏览器中,entry还包括下面两个属性值,borderBoxSize对象和contentBoxSize对象。

entry.borderBoxSize
entry.contentBoxSize

都返回ResizeObserverSize对象,该对象展开为:

{ 
    inlineSize: 271,
    blockSize: 41
}

其中inlineSize表示内联元素排列方向上的尺寸,等同于CSS逻辑属性 inline-size ,在默认文档流下表示宽度;blockSize表示块级元素排列方向上的尺寸,等同于CSS逻辑属性 block-size ,在默认文档流下表示高度。

三、ResizeObserver实际应用案例

1. 原生resize行为的检测

例如,有了ResizeObserver,我们就可以检测