vue中使用keep-alive缓存后处于disactivated状态的echarts表格自适应功能(resize)失效的解决办法

vue中使用keep-alive缓存后处于disactivated状态的echarts表格自适应功能(resize)失效的解决办法

问题介绍

在vue开发中的时候,由于项目需要,在不同路由的页面使用了大量echarts,由于展示页面用的机子太垃圾,只能给每个路由都加上keep-alive缓存,来获得可怜的流畅度。

<template>
    <el-container class="home">
        <el-header>
            <keep-alive>
                <selfHeader></selfHeader>
            </keep-alive>
        </el-header>
        <el-main>
            <transition :name="transitionName">
                <keep-alive>
                    <router-view></router-view>
                </keep-alive>
            </transition>
        </el-main>
    </el-container>
</template>

同时,我们为每个echarts都加上了自适应窗口大小的功能。

cityComplementBar.setOption(option)
window.addEventListener('resize', () => {
            cityComplementBar.resize()
        })

重点来了,在这个时候,打开咋一看没啥问题,但是当你将缓存好的页面切换到后台时(即处于disactivated状态),如果改变当前页面窗口大小,那么bug就来了。之前缓存好的页面再打开时,echarts就没了。。。就没了。。。看一下后台,还疯狂报错,咋回事呢?
在这里插入图片描述
分析一波,之前为了实现echarts的自适应,添加了一个监听器监测window窗口是否发生变化,如果变化了就执行echarts自带的resize方法来改变一下echarts的大小,并且将这个方法习惯性地写在了生成echarts的方法中。但是,我们加入缓存后情况就有点不一样了。我们绘制Echarts的方法是写在mounted生命周期中的,而切换页面并会不会进入destroyed生命周期,而是进入disactivated生命周期,这使得mounted中的函数还是激活状态,我们之前添加的监听器仍然在工作,但是但是但是,之前缓存页面的dom没了啊,我们的eventListener监听到了别人家的dom变了,于是想重画一下自家的echarts,但是你连画板都没有啊,画啥?于是echarts-gl开始发出上文提到的警告。echarts-gl源文件中存在这一段代码(报错的根源):

if (!zr.getWidth() || !zr.getHeight()) {
        console.warn('Dom has no width or height');
        return;
    }

然后,当你切换回已缓存的页面时,bug就来了。echarts消失了。
在这里插入图片描述
然后你再改变一下宽口大小,echarts又回来了。。。
在这里插入图片描述
这是因为你之前你改变dom的时候,echarts重画失败了,可是你切回来的时候,dom虽然相对于你切出去之前可能变了,但是对于监听器来说,他只关注于当前dom大小是否改变了。所以刚切回来的时候echarts的resize方法不会被激活。而只要稍稍改变一下dom的大小,就可以激活resize方法。

解决办法

咋办呢?我用的方法其实挺简单的。首先,在data中注册一个全局的变量。

data() {
        return { cityComplementBar: null }
    },

然后,把dom中用于绘制echarts的id赋值到注册的全局变量中

this.cityComplementBar = echarts.init(document.getElementById('cityComplementBar'));

随后,不管是注册echarts还是setOption,或者resize都在这个全局变量上执行就行了。特别注意,监听dom的监听器如果要拿出来单独写一个函数,必须要添加在mounted中才能使用,放在activated中就失效了。
接着,就可以在activated生命周期中单独给一个resize方法,不管他窗口大小是否变化了,都resize一次。

    mounted() {
        this.getData()
        window.addEventListener('resize', () => {
            this.cityComplementBar.resize()
        })
    },
    activated() {
        if (this.cityComplementBar) {
            this.cityComplementBar.resize()
        }
    },

最后

如果不想改源文件的话可以在deactivated生命周期取消window的尺寸监听器,每次在activated的时候都添加一个监听器就行,但是注意一定要执行一次resize,不然你中途变了窗口大小监听器可没监听到,会bug的。初次总结,欢迎指教,不足之处,请多包容。谢谢~

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值