完美监听一个div尺寸的改变(不论何种方式导致的尺寸变化)

前言

我们知道resize或者onResize事件是window才有的事件。
如图:
Honeycam 2019-12-31 12-05-59.gif
我们可以看到在最右侧,改变window的宽度,此时在左侧的chart div中监听到 window的resize后,做出了改变。也向右移动。

但是如果我们测试不改变window,而只是改变div的宽度呢?
如图:
Honeycam 2019-12-31 12-12-01.gif
我们让chart div右侧的 div消失(v-if设置为false)。
此时chart div中的window resize事件并没有监听到。
左侧的chart div没变,这不是我们要的效果。

第三种,如果我们动态改变css中的width呢?
如图
Honeycam 2019-12-31 12-19-09.gif
我们改变了chart div的width值,我们发现当width变得越来越小时,chart div的宽度也并没有改变(出现了横向滚动条而已)。说明也没监听到。
这也不是我们要的效果。

方案一

我们可以在chart div平级的位置,放置一个object元素。
设置object的css,使得object撑满父元素的宽高。

 <!-- chart区域 -->
<div id="histogram"
    ref="chart">
</div>

<!-- object区域 -->
<object ref="objectRef"
    tabindex="-1"
    type="text/html"
    aria-hidden="true"
    data="about:blank"
    style="display: block; 
            position: absolute; 
            top: 0px; 
            left: 0px; 
            width: 100%; 
            height: 100%; 
            border: none; 
            padding: 0px; 
            margin: 0px; 
            opacity: 0; 
            z-index: -1000; 
            pointer-events: none;">
</object>

此时在js中我们可以监听这个object的大小。只要监听到object大小变了,那么不就意味间接监听到chart div改变了吗?

//注意。通过this.$refs["objectRef"]获取到object之后,还要通过属性.contentDocument.defaultView获取到最里层的window document部分

this.$refs["objectRef"].contentDocument.defaultView

image.png

这样,而且通过打印到控制台的log可以看到
image.png

this.$refs["objectRef"].contentDocument.defaultView的返回值就是window。

既然是window,那不就有了resize事件吗?

this.$refs["objectRef"].contentDocument.defaultView.addEventListener("resize", () => {
    this.$chart.resize();
});

如此便可以完美监听chart div的改变,然后对chart进行重绘。

Honeycam 2019-12-31 13-09-26.gif

方案二

使用 ResizeObserver api,详情请查看这个链接

它的使用方式非常简单。

const resizeObserver = new ResizeObserver(entries => {
    //回调
    this.$chart.resize();
});

//监听对应的dom
resizeObserver.observe(this.$refs.chart);

但是坏处是,兼容性不高。
image.png

不过github上,已经提供了能够兼容至IE9的 resizeObserver polyfill。我们只需要安装他即可。

yarn add @juggle/resize-observer
然后引入至页面。

import ResizeObserver from '@juggle/resize-observer';

便可以像上面那样,正常使用resizeObserver。

后续有其他方案,再补充。。。

阅读 797

推荐阅读
小李子的前端
用户专栏

热爱前端的菜鸟,怀揣梦想的小白

25 人关注
15 篇文章
专栏主页