Vue 3 开发中的 ECharts 5 使用


随着 Vue 更新到了 V3 版本,ECharts 更新到了 V5 版本,它们均新增加了对 TypeScript 非常友好的支持。鉴于现有的开发方式与原先 Vue V2 版本仍然具有一些区别,所以本文在此给出一个新版的开发样例。


1. 示例代码

本节以标准柱形图为例,使用 Composition API 以及 TypeScript 进行代码编写。

TestChart.vue

<template>
  <div ref="chartRef" style="width: 100%; height: 400px"></div>
</template>

<script lang="ts">
import { defineComponent, onBeforeUnmount, onMounted, ref } from "vue";
import * as echarts from "echarts/core";
import { BarChart } from "echarts/charts";
import {
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
} from "echarts/components";
import { LabelLayout } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
import { useChartData } from "./useChart";

export default defineComponent({
  name: "TestChart",
  setup() {
    const chartRef = ref<HTMLDivElement>();
    let chart: echarts.ECharts | null = null;
    echarts.use([
      BarChart,
      TooltipComponent,
      GridComponent,
      DataZoomComponent,
      LabelLayout,
      CanvasRenderer,
    ]);

    const { initOption } = useChartData();

    const resizeHandler = () => {
      chart?.resize();
    };

    onMounted(() => {
      chart = echarts.init(chartRef.value as HTMLDivElement);
      chart.setOption(initOption);

      window.addEventListener("resize", resizeHandler);
    });

    onBeforeUnmount(() => {
      window.removeEventListener("resize", resizeHandler);
      chart?.dispose();
    });

    return {
      chartRef,
    };
  },
});
</script>

当然,也可以使用 script setup 版本的代码:

TestChart.vue script setup:

<template>
  <div ref="chartRef" style="width: 100%; height: 400px"></div>
</template>

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from "vue";
import * as echarts from "echarts/core";
import { BarChart } from "echarts/charts";
import {
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
} from "echarts/components";
import { LabelLayout } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
import { useChartData } from "./useChart";

const chartRef = ref<HTMLDivElement>();
let chart: echarts.ECharts | null = null;
echarts.use([
  BarChart,
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  LabelLayout,
  CanvasRenderer,
]);

const { initOption } = useChartData();

const resizeHandler = () => {
  chart?.resize();
};

onMounted(() => {
  chart = echarts.init(chartRef.value as HTMLDivElement);
  chart.setOption(initOption);

  window.addEventListener("resize", resizeHandler);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", resizeHandler);
  chart?.dispose();
});
</script>

useChart.ts

import * as echarts from "echarts/core";
import { BarSeriesOption } from "echarts/charts";
import {
  TooltipComponentOption,
  GridComponentOption,
  DataZoomComponentOption,
} from "echarts/components";

export type ECOption = echarts.ComposeOption<
  | BarSeriesOption
  | TooltipComponentOption
  | GridComponentOption
  | DataZoomComponentOption
>;

export function useChartData(): {
  initOption: ECOption;
} {
  const initOption: ECOption = {
    tooltip: {
      trigger: "axis",
      axisPointer: {
        type: "shadow",
      },
    },
    xAxis: [
      {
        type: "category",
        data: ["A", "B", "C", "D", "E"],
        axisTick: {
          alignWithLabel: true,
        },
      },
    ],
    yAxis: [
      {
        type: "value",
      },
    ],
    dataZoom: [
      {
        type: "inside",
        orient: "horizontal",
      },
      {
        type: "slider",
        orient: "horizontal",
        start: 0,
        end: 100,
      },
    ],
    series: [
      {
        type: "bar",
        data: [123, 332, 22, 1, 23],
        label: {
          show: true,
          position: "top",
        },
        itemStyle: {
          color: "#27727B",
        },
        labelLayout: {
          hideOverlap: true,
        },
        emphasis: {
          label: {
            show: true,
            fontWeight: "bolder",
            fontSize: 15,
          },
          itemStyle: {
            shadowColor: "rgba(0, 0, 0, 0.7)",
            shadowBlur: 10,
          },
        },
      },
    ],
  };

  return {
    initOption,
  };
}

参考链接:


2. 关于控制台报错 `resize` should not be called during main process

一般情况下,对 ECharts 图表封装并不需要将 echarts 对象暴露到渲染上下文中。如果确实有意将 echarts 对象声明为响应式,请使用 shallowRef 而非 ref

// GOOD
const chart = shallowRef<echarts.ECharts>(); 

// BAD
const chart = ref<echarts.ECharts>();

如果不使用 shallowRef,可能会导致命令行报错 `resize` should not be called during main process;事实上,任何第三方库创造的实例都应当使用 shallowRef 而非 ref 进行响应式处理。

参考链接:

Logo

前往低代码交流专区

更多推荐