这里使用vue3+vite+ts

Echarts

下载echarts

npm install echarts

TS的按需引入

引入echarts组件

在 src/plugins 文件下新建echarts.ts

// src/plugins/echarts.ts
import * as echarts from "echarts/core";
import {
  BarChart,
  // 系列类型的定义后缀都为 SeriesOption
  BarSeriesOption,
  LineChart,
  LineSeriesOption,
} from "echarts/charts";
import {
  TitleComponent,
  // 组件类型的定义后缀都为 ComponentOption
  TitleComponentOption,
  TooltipComponent,
  TooltipComponentOption,
  GridComponent,
  GridComponentOption,
  // 数据集组件
  DatasetComponent,
  DatasetComponentOption,
  // 内置数据转换器组件 (filter, sort)
  TransformComponent,
} from "echarts/components";
import { LabelLayout, UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";

// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = echarts.ComposeOption<
  | BarSeriesOption
  | LineSeriesOption
  | TitleComponentOption
  | TooltipComponentOption
  | GridComponentOption
  | DatasetComponentOption
>;

// 注册必须的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  BarChart,
  LineChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer,
]);


export default echarts;

在main.ts中导入,并挂载到全局属性上:

import { createApp } from "vue";
// ...
import echarts from "@/plugins/echarts";

const app = createApp(App);

app.config.globalProperties.$echarts = echarts;
// ...
app.mount("#app")

使用

首先要把 getCurrentInstance() 方法的做层封装,当然不封装直接使用也可以:

// src/hooks/useCurrentInstance.ts
import { ComponentInternalInstance, getCurrentInstance } from 'vue'
export default function useCurrentInstance() {
  const { appContext } = getCurrentInstance() as ComponentInternalInstance
  const proxy = appContext.config.globalProperties
  return {
    proxy
  }
}

vue页面:

<template>
  <div
    class="echarts-wrap"
    v-loading="loading"
    element-loading-text="Loading..."
  >
    <div class="chart" ref="chartDom"></div>
  </div>
</template>

<script setup lang="ts" name="Echarts">
import {
  ref,
  reactive,
  watch,
  onMounted,
  onActivated,
  onUnmounted,
  computed,
  nextTick,
} from "vue";
import { useRoute } from "vue-router";
import { useAppStore } from "@/store/app";
import { useTagsViewStore } from "@/store/tagsView";
import useCurrentInstance from "@/hooks/useCurrentInstance";
import { chartData } from "@/api/echart";
const { proxy } = useCurrentInstance();
const route = useRoute();
const appStore = useAppStore();
const tagsViewStore = useTagsViewStore();
onMounted(() => {
  getData();
  nextTick(() => {
    initEchart();
  });
});
// 这里没有页面缓存可以删掉
onActivated(() => {
  if (chart.value) return;
  initEchart();
});
// 组件销毁删除echarts
onUnmounted(() => {
  chart.value.dispose();
});

// watch这里没有缓存和菜单栏折叠可以删掉
watch(
  () => appStore.sidebar,
  (n) => {
    {
      // 这里监听菜单栏的折叠和收起导致宽度的变化,需要重新渲染
      // 如果页面被缓存,那在其他页面做菜单栏的折叠和收起也会监听到,所以要做判断
      if (
        tagsViewStore.cachedViews.includes("Echarts") &&
        route.name !== "Echarts"
      )
        return;
      
      setTimeout(() => {
        initEchart();
      }, 500);
    }
  }
);
const setOptions = computed(() => {
  return {
    title: {
      text: "ECharts展示",
    },
    tooltip: {},
    grid: {
      right: "15px",
    },
    xAxis: {
      data: resData.xData,
    },
    yAxis: {},
    series: [
      {
        name: "销量",
        type: "bar",
        data: resData.yData,
      },
    ],
  };
});
const loading = ref(true);
const chartDom = ref(); // 获取ref dom元素
const resData = reactive({
  xData: [] as string[],
  yData: [] as string | number[],
});
const chart = ref<any>(null); // echarts

const getData = async () => {
  const res = await chartData();
  if (res.code != 200) return;
  if (res.data) {
    resData.xData = res.data.map((v: { label: string }) => {
      return v.label;
    });
    resData.yData = res.data.map((v: { value: string }) => {
      return v.value;
    });
  }
  loading.value = false;
  chart.value.setOption(setOptions.value);
};

const initEchart = () => {
  if (chart.value) {
    chart.value.dispose();
  }
  // 获取dom,断言HTMLElement类型
  const chartEle: HTMLElement = chartDom.value as HTMLElement;
  chart.value = proxy.$echarts.init(chartEle);
  chart.value.setOption(setOptions.value);
  window.onresize = function () {
    chart.resize();
  };
};
</script>

<style lang="scss" scoped>
.echarts-wrap {
  padding: 15px;
  .chart {
    width: 100%;
    height: 300px;
  }
}
</style>

image.png

demo

使用Vue3+Vite+Ts 技术栈,自己搭建的管理系统,感兴趣的同学可以给个start~
演示地址:http://120.46.214.138:8080/
gitee地址:https://gitee.com/Divenl/vue3-vite-ts-admin

Logo

前往低代码交流专区

更多推荐