vue3+ts图表组件

子组件

<template>
  <div ref="echartsContainer" :style="containerStyles"></div>
</template>

<script setup lang="ts">
import { defineProps, ref, onMounted, onBeforeUnmount, watch, watchEffect } from 'vue';
import * as echarts from 'echarts';

const props = defineProps(['chartOptions', 'styles', 'isMenuCollapsed', 'chartData']);

const echartsContainer = ref<HTMLElement | null>(null);
let chart: echarts.ECharts | null = null;

const containerStyles = computed(() => {
  return {
    ...props.styles,
  };
});

// 创建图表
const createChart = () => {
  if (echartsContainer.value) {
    chart = echarts.init(echartsContainer.value);
    chart.setOption(props.chartOptions);
  }
};
// 自适应方法
const resizeChart = () => {
  if (chart) {
    chart.resize();
  }
};
 // 监听窗口大小变化
onMounted(() => {
  createChart();
  window.addEventListener('resize', resizeChart);
});
onBeforeUnmount(() => {
  if (chart) {
    window.removeEventListener('resize', resizeChart);
    chart.dispose();
  }
});
// 监听菜单折叠状态的变化,调整图表
watch(props.chartOptions, () => {
  if (chart) {
    // 当 props.chartData 变化时更新图表数据
    chart.setOption(props.chartOptions, true);
    resizeChart();
  }
  resizeChart();
});
</script>

父组件使用

<template>
<div>
    <EChartsComponent :chartOptions="chartOptions" :styles="{ width: '100%', height : '400px' }" />
</div>
</template>

<script setup lang="ts">
import EChartsComponent from './components/EChartsComponent.vue';

// 柱状图
const chartOptions = ref({
  color: ['#0C80B9', '#EF9847', '#F6E021', '#0066FF'],
  grid: {
    left: 15,
    top: 60,
    right: 80,
    bottom: 0,
    containLabel: true
  },
  title: {
    show: false,
    text: '暂无数据',
    left: 'center',
    top: 'middle',
    textStyle: {
      fontSize: 24,
      fontWeight: 'normal'
    }
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'shadow'
    },
    borderWidth: 0,
    backgroundColor: 'rgba(0,0,0,0.8)',
    textStyle: {
      color: '#FFFFFF'
    }
  },
  legend: {
    itemWidth: 12,
    itemHeight: 8,
    left: 15,
    itemGap: 16,
    textStyle: {
      color: '#49445F',
      fontWight: 'bold',
      fontFamily: '微软雅黑',
      fontSize: 12
    },
    data: ['类型一', '类型二', '类型三']
  },
  xAxis: [
    {
      type: 'category',
      name: '单位:岁',
      nameLocation: 'end',
      nameGap: 10,
      nameTextStyle: {
        color: '#A9A6B7',
        fontFamily: 'Arial'
      },
      axisTick: { show: false },
      // axisLine: { show: false },
      axisLabel: {
        show: true,
        color: '#A9A6B7'
      },
      lineStyle: {
        color: '#000000'
      },
      data: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
    }
  ],
  yAxis: [
    {
      type: 'value',
      name: '单位:人',
      nameTextStyle: {
        color: '#A9A6B7',
        fontFamily: 'Arial'
      },
      axisTick: { show: false },
      axisLine: { show: false },
      splitLine: {
        show: true,
        lineStyle: {
          color: '#E3EAEF'
        }
      }
    }
  ],
  series: [
    {
      name: '类型一',
      type: 'bar',
      barGap: '40%',
      // barWidth: 16,
      barMaxWidth: 16,
      barMinWidth: 8,
      emphasis: {
        focus: 'series'
      },
      data: [200,150,130,150,200,80,50]
    },
    {
      name: '类型二',
      type: 'bar',
      barGap: '40%',
      // barWidth: 16,
      barMaxWidth: 16,
      barMinWidth: 8,
      emphasis: {
        focus: 'series'
      },
      data: [100,80,60,150,200,130,100]
    },
    {
      name: '类型三',
      type: 'bar',
      barGap: '40%',
      // barWidth: 16,
      barMaxWidth: 16,
      barMinWidth: 8,
      emphasis: {
        focus: 'series'
      },
      data: [80,150,150,200,100,80,100]
    }
  ]
});
</script>

-End-