vue element的tabs中使用echarts

 tabs中使用echarts,除了第一个图表能默认显示外,当tabs切换的时候,第一个之后的可能就显示不了了,如何解决?

<template>
  <div>
    <el-row>
      <el-col :span="24">
        <el-card>
          <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
            <el-tab-pane label="用户管理" name="first" lazy>
              <div id="user-manage"></div>
            </el-tab-pane>
            <el-tab-pane label="配置管理" name="second" lazy>
              <div id="config-manage"></div>
            </el-tab-pane>
            <el-tab-pane label="角色管理" name="third" lazy>
              <div id="role-manage"></div>
            </el-tab-pane>
            <el-tab-pane label="定时任务补偿" name="fourth" lazy>
              <div id="task-compensation"></div>
            </el-tab-pane>
          </el-tabs>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeName: "first"
    };
  },
  methods: {
    drawLine() {
      const lineChart = this.$echarts.init(
        document.getElementById("alarm-trend")
      );

      const option = {
        xAxis: {
          type: "category",
          data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
        },
        yAxis: {
          type: "value"
        },
        series: [
          {
            data: [150, 230, 224, 218, 135, 147, 260],
            type: "line"
          }
        ]
      };

      lineChart.setOption(option);
    },
    drawBar() {
      const barChart = this.$echarts.init(
        document.getElementById("user-manage")
      );

      const option = {
        xAxis: {
          type: "category",
          data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
        },
        yAxis: {
          type: "value"
        },
        series: [
          {
            data: [120, 200, 150, 80, 70, 110, 130],
            type: "bar",
            showBackground: true,
            backgroundStyle: {
              color: "rgba(180, 180, 180, 0.2)"
            }
          }
        ]
      };

      barChart.setOption(option);
    },
    drawPie() {
      const pieChart = this.$echarts.init(
        document.getElementById("config-manage")
      );

      const option = {
        title: {
          text: "某站点用户访问来源",
          subtext: "纯属虚构",
          left: "center"
        },
        tooltip: {
          trigger: "item"
        },
        legend: {
          orient: "vertical",
          left: "left"
        },
        series: [
          {
            name: "访问来源",
            type: "pie",
            radius: "50%",
            data: [
              { value: 1048, name: "搜索引擎" },
              { value: 735, name: "直接访问" },
              { value: 580, name: "邮件营销" },
              { value: 484, name: "联盟广告" },
              { value: 300, name: "视频广告" }
            ],
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)"
              }
            }
          }
        ]
      };

      pieChart.setOption(option);
    },
    drawGrandpa() {
      const grandpaChart = this.$echarts.init(
        document.getElementById("role-manage")
      );

      const data = [
        {
          name: "Grandpa",
          children: [
            {
              name: "Uncle Leo",
              value: 15,
              children: [
                {
                  name: "Cousin Jack",
                  value: 2
                },
                {
                  name: "Cousin Mary",
                  value: 5,
                  children: [
                    {
                      name: "Jackson",
                      value: 2
                    }
                  ]
                },
                {
                  name: "Cousin Ben",
                  value: 4
                }
              ]
            },
            {
              name: "Father",
              value: 10,
              children: [
                {
                  name: "Me",
                  value: 5
                },
                {
                  name: "Brother Peter",
                  value: 1
                }
              ]
            }
          ]
        },
        {
          name: "Nancy",
          children: [
            {
              name: "Uncle Nike",
              children: [
                {
                  name: "Cousin Betty",
                  value: 1
                },
                {
                  name: "Cousin Jenny",
                  value: 2
                }
              ]
            }
          ]
        }
      ];

      const option = {
        series: {
          type: "sunburst",
          // emphasis: {
          //     focus: 'ancestor'
          // },
          data: data,
          radius: [0, "90%"],
          label: {
            rotate: "radial"
          }
        }
      };

      grandpaChart.setOption(option);
    },
    drawRadar() {
      const radarChart = this.$echarts.init(
        document.getElementById("task-compensation")
      );

      const option = {
        title: {
          text: "基础雷达图"
        },
        tooltip: {},
        legend: {
          data: ["预算分配(Allocated Budget)", "实际开销(Actual Spending)"]
        },
        radar: {
          // shape: 'circle',
          name: {
            textStyle: {
              color: "#fff",
              backgroundColor: "#999",
              borderRadius: 3,
              padding: [3, 5]
            }
          },
          indicator: [
            { name: "销售(sales)", max: 6500 },
            { name: "管理(Administration)", max: 16000 },
            { name: "信息技术(Information Techology)", max: 30000 },
            { name: "客服(Customer Support)", max: 38000 },
            { name: "研发(Development)", max: 52000 },
            { name: "市场(Marketing)", max: 25000 }
          ]
        },
        series: [
          {
            name: "预算 vs 开销(Budget vs spending)",
            type: "radar",
            // areaStyle: {normal: {}},
            data: [
              {
                value: [4300, 10000, 28000, 35000, 50000, 19000],
                name: "预算分配(Allocated Budget)"
              },
              {
                value: [5000, 14000, 28000, 31000, 42000, 21000],
                name: "实际开销(Actual Spending)"
              }
            ]
          }
        ]
      };

      radarChart.setOption(option);
    },
    handleClick(tab, event) {
      switch (this.activeName) {
        case "first":
          this.$nextTick(() => {
            this.drawBar();
          });
          break;
        case "second":
          this.$nextTick(() => {
            this.drawPie();
          });
          break;
        case "third":
          this.$nextTick(() => {
            this.drawGrandpa();
          });
          break;
        case "fourth":
          this.$nextTick(() => {
            this.drawRadar();
          });
          break;
        default:
          this.$nextTick(() => {
            this.drawBar();
          });
      }
    }
  },
  mounted() {
    this.drawBar();
  }
};
</script>

<style scoped>
#user-manage {
  height: 300px;
}
#config-manage {
  height: 300px;
}
#role-manage {
  height: 300px;
}
#task-compensation {
  height: 300px;
}
</style>

其中的关键是handleClick函数和$nextTick函数。

### Vue使用 `el-tabs` 切换时销毁 ECharts 实例的解决方案 在 VueElement UI 的开发场景下,当使用 `el-tabs` 组件并嵌入 ECharts 图表时,可能会遇到因标签页切换而导致的图表渲染异常问题。例如,在切换标签页时,ECharts 图表可能未能正确响应其容器尺寸的变化[^1]。 #### 问题原因分析 - 当某个标签页未被激活时,该页面的内容通常会被隐藏(即设置为 `display: none`),这会导致 ECharts 容器的实际宽度变为 0 或者无法正常计算。 - 如果不手动处理 ECharts 实例的状态管理,则可能导致旧实例残留或者新实例初始化失败等问题[^3]。 #### 解决策略 为了确保每次切换标签页时都能正确加载和更新 ECharts 图表,可以采取以下措施: 1. **监听 Tab 切换事件** 使用 `@tab-click` 或 `watch` 来捕获当前活动的标签页索引变化,并在此基础上执行必要的逻辑操作。 2. **销毁已有的 ECharts 实例** 在离开当前标签页前调用 `chart.dispose()` 方法显式销毁现有的 ECharts 实例,从而释资源并防止冲突。 3. **重新初始化 ECharts 实例** 进入目标标签页后再次创建新的 ECharts 实例,并通过 `resize` 方法强制刷新图表布局以适配最新的 DOM 尺寸。 以下是具体实现代码示例: ```javascript <template> <el-tabs v-model="activeTab" @tab-click="handleTabClick"> <el-tab-pane label="Tab A" name="first">...</el-tab-pane> <el-tab-pane label="Tab B" name="second"> <div ref="chartContainer" style="width: 100%; height: 400px;"></div> </el-tab-pane> </el-tabs> </template> <script> export default { data() { return { activeTab: 'first', chartInstance: null, }; }, methods: { handleTabClick(tab) { const targetName = tab.paneName; if (targetName === 'second') { // 初始化第二个标签中的 ECharts 图表 this.initChart(); } else { // 销毁第一个标签对应的 ECharts 图表实例 this.destroyChart(); } }, initChart() { if (!this.chartInstance) { this.chartInstance = this.$echarts.init(this.$refs.chartContainer); const option = { title: { text: 'Sample Chart' }, tooltip: {}, xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] }, yAxis: { type: 'value' }, series: [{ data: [820, 932, 901], type: 'line' }] }; this.chartInstance.setOption(option); window.addEventListener('resize', () => this.chartInstance.resize()); } this.chartInstance.resize(); // 调整图表大小 }, destroyChart() { if (this.chartInstance) { this.chartInstance.dispose(); // 显式销毁实例 this.chartInstance = null; window.removeEventListener('resize', () => {}); // 移除窗口调整监听器 } } }, beforeDestroy() { this.destroyChart(); // 防止组件卸载时遗留未清理的实例 } }; </script> ``` 上述方法能够有效应对由于标签切换引发的各种兼容性和性能隐患[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值