6

前言

我们知道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

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


寒水寺一禅
2.3k 声望119 粉丝

人生短短急个球!