最近在做Echarts图表切换的时候遇到了一个坑,产品设计的需求是这样,两个tab,一个是疾病风险图表,一个是意外风险图表,tab切换时显示不同的图表,而且要根据不同角色的年龄动态的在图表上打个坐标点,页面里面用的是v-show,没有用v-if,当时是这样考虑的,页面初始化进来加载的数据就直接都渲染了,因为v-show不会隐藏dom结构,点击tab切换就行了,但实际证明是我的想法太天真,这样写就会出现很多莫名其妙的问题。

 

vue echarts图表转换不了rem_v-show

首先来描述一下出现的不友好的问题:

(1)两个tab来回切换的时候Echarts的坐标线tooltip有时候显示,有时候不显示

(2)当年龄比较大的时候,比如说57岁,tooltip描述就会显示到表格外面,超出手机屏幕,不会友好的适配显示到坐标线的左侧

(3)两个tab切换的时候,两个图标传入的值不一样,纵坐标的间隔却不会变

最开始的时候,产品那边提到这些问题,自己以为是图表插件本身的问题,觉得是不是图表本身对手机端适配的不好,后来好好的研究了一番,发现是图表渲染高度的问题,找到了问题的所在,就有办法解决了,网上搜了各种办法,说是高度要重新设置什么的,因为我项目用的预编译器是stylus,适配用的vw方式,如果在调用图表加载的方法的时候动态加个高度,这样样式就不走预编译器,达不到适配手机屏幕的效果了,所以我想了想,既然问题的本质就是要重新渲染图表,那我就重新换一种方式,借助vue的v-if标签来重新渲染dom结构。

解决方案:

(1)把两个tab的v-show切换方式换成v-if,因为v-if能够重新渲染dom结构

<div class="risk-chart-content" v-if="isShowTabLeft">
              <p class="risk-chart-title">疾病风险分析</p>
              <div id="myChat" ref="pieEchartsleft"></div>
            </div>
            <div class="risk-chart-content" v-if="isShowTabRight">
              <p class="risk-chart-title">意外风险分析</p>
              <div id="myChatRight" ref="pieEchartsRight"></div>
            </div>

(2)在tab切换触发的函数下面用$nextTick()加载图表渲染

<div class="risk-tab">
            <div class="risk-tab-public"
                 v-bind:class="{riskTabLight: isShowTabLeft}"
                 @click="changeTab(1)">疾病风险
            </div>
            <div class="risk-tab-public"
                 v-bind:class="{riskTabLight: isShowTabRight}"
                 @click="changeTab(2)">意外风险
            </div>
          </div>
changeTab(tab) {
        if (tab === 1) {
          this.isShowTabLeft = true;
          this.isShowTabRight = false;
            this.$nextTick(() => {
              this.drawLine(); // 加载疾病风险图表
            });
        } else {
          this.isShowTabLeft = false;
          this.isShowTabRight = true;
            this.$nextTick(() => { 
              this.drawLineRight(); // 加载意外风险图表
            });
        }
      },

这样就完美的解决了图表显示的问题。

另外:产品还要求年龄tooltip在图表上的位置不能动,打的坐标点,初始化进来要固定到图表上,我查了一下图表的配置文档,也没有找到合适的方式,如果有知道方法的,可以告知我一下,我这里用了一个极端的方式,添加了一个css样式禁止点击,成功的解决了这个问题。

#myChat
            wh(686px, 400px)
            padding 0
            margin 0
            margin-bottom 20px
            pointer-events none  // 禁止触发事件
          #myChatRight
            wh(686px, 400px)
            padding 0
            margin 0
            margin-bottom 20px
            pointer-events none // 禁止触发事件