封装一个通用的Vue3-Echarts基础组件

3,258 阅读1分钟

工作中做了几个大屏可视化项目,必用Echarts,通常一个页面中会有多个Echarts图表,避免重复渲染,代码冗余将Echarts的基础配置封装成了一个共用组件

共用组件:

<template>
  <div ref="chartRef" :style="{ height }" />
</template>

<script>
import { defineComponent, getCurrentInstance, onMounted, onBeforeMount, onBeforeUnmount, nextTick, watchEffect} from "vue";
//引入echarts
import * as echarts from "echarts";

//如果需要中国地图
import china from '@/assets/js/china.json';
echarts.registerMap('china', china);

//如果需要tooltip自动轮播
import tools from '@/utils/tooltip-auto-show-vue';

let chartsArr = [];
export default defineComponent({
  name: "BaseEcharts",
  props: {
    height: {
      type: String,
      default: "300px",
    },
    options: {
      type: Object,
      default: () => ({})
    },
  },
  setup(props) {
  //setup执行时组件对象还没有创建,我们可以通过 getCurrentInstance这个函数来返回当前组件的实例对象
    const { proxy } = getCurrentInstance();
    const initCharts = () => {
      //通过Promise异步操作,避免报错Initialize failed: invalid dom
      //1:新建一个promise对象
      let newPromise = new Promise((resolve) => {
        resolve();
      });
      // 2:然后异步执行echarts的初始化函数
      newPromise.then(() => {
        const myChart = echarts.init(proxy.$refs.chartRef);
        let tootipTimer = null;
        //侦听配置改变后重新渲染,必须放在newPromise.then()中,否则会出现异步问题,每次渲染都是上一次的结果
        watchEffect(()=>{
          myChart.setOption(props.options);
          tootipTimer && tootipTimer.clearLoop();
          tootipTimer = null;
          tootipTimer = tools.loopShowTooltip(myChart, props.options, {
            interval: 3000, // 轮播间隔时间
            loopSeries: true // 是否开启轮播循环
          });
        })
        chartsArr.push(myChart);
      });

    };
    //窗口resize事件
    const handleChartResize = () => {
      for(var i = 0;i < chartsArr.length;i++) {
        chartsArr[i] && chartsArr[i].resize();
      }
    };
    onBeforeMount(() => {
      nextTick(() => {
        initCharts();
      });
    });
    onMounted(() => {
      window.addEventListener("resize", handleChartResize);
    });
    onBeforeUnmount(() => {
      window.removeEventListener('resize', handleChartResize);;
    });
    return {

    };
  }
});
</script>

<style lang="scss" scoped></style>

view中使用:

<template>
     <BaseEcharts :options="options" :height="echartsHeight" style="width:100%"/>
</template>
<script setup>
    import BaseEcharts from './BaseEcharts.vue'
    //设置图表高度
    const echartsHeight = '300px'
    //图表自定义配置
    const options = {
    ...
    }
<script>