Vue 3项目中引用ECharts并设计多种图表组件的实现方案

发布于:2025-09-08 ⋅ 阅读:(15) ⋅ 点赞:(0)

以下是一个完整的Vue 3项目中引用ECharts并设计多种图表组件的实现方案:

安装依赖

npm install echarts vue-echarts

基础封装组件

components/ECharts.vue中创建基础封装:

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

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import * as echarts from 'echarts';

const props = defineProps({
  options: Object,
  width: { type: String, default: '100%' },
  height: { type: String, default: '400px' }
});

const chartRef = ref(null);
let chartInstance = null;

const initChart = () => {
  if (chartRef.value) {
    chartInstance = echarts.init(chartRef.value);
    props.options && chartInstance.setOption(props.options);
  }
};

const resizeChart = () => {
  chartInstance?.resize();
};

onMounted(() => {
  initChart();
  window.addEventListener('resize', resizeChart);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeChart);
  chartInstance?.dispose();
});

watch(() => props.options, (newVal) => {
  chartInstance?.setOption(newVal);
}, { deep: true });
</script>

柱状图组件

components/BarChart.vue中:

<template>
  <ECharts :options="chartOptions" :width="width" :height="height" />
</template>

<script setup>
import ECharts from './ECharts.vue';

const props = defineProps({
  data: Array,
  xAxis: Array,
  width: { type: String, default: '100%' },
  height: { type: String, default: '400px' }
});

const chartOptions = {
  tooltip: {
    trigger: 'axis'
  },
  xAxis: {
    type: 'category',
    data: props.xAxis
  },
  yAxis: {
    type: 'value'
  },
  series: [{
    data: props.data,
    type: 'bar',
    showBackground: true,
    backgroundStyle: {
      color: 'rgba(180, 180, 180, 0.2)'
    }
  }]
};
</script>

折线图组件

components/LineChart.vue中:

<template>
  <ECharts :options="chartOptions" :width="width" :height="height" />
</template>

<script setup>
import ECharts from './ECharts.vue';

const props = defineProps({
  series: Array,
  xAxis: Array,
  width: { type: String, default: '100%' },
  height: { type: String, default: '400px' }
});

const chartOptions = {
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: props.series.map(item => item.name)
  },
  xAxis: {
    type: 'category',
    data: props.xAxis
  },
  yAxis: {
    type: 'value'
  },
  series: props.series.map(item => ({
    ...item,
    type: 'line',
    smooth: true
  }))
};
</script>

饼图组件

components/PieChart.vue中:

<template>
  <ECharts :options="chartOptions" :width="width" :height="height" />
</template>

<script setup>
import ECharts from './ECharts.vue';

const props = defineProps({
  data: Array,
  width: { type: String, default: '100%' },
  height: { type: String, default: '400px' }
});

const chartOptions = {
  tooltip: {
    trigger: 'item'
  },
  series: [
    {
      name: '占比',
      type: 'pie',
      radius: ['40%', '70%'],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 10,
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false,
        position: 'center'
      },
      emphasis: {
        label: {
          show: true,
          fontSize: '18',
          fontWeight: 'bold'
        }
      },
      data: props.data
    }
  ]
};
</script>

使用示例

在页面中使用这些组件:

<template>
  <div class="chart-container">
    <BarChart 
      :data="barData" 
      :xAxis="barXAxis" 
      height="300px" 
    />
    
    <LineChart 
      :series="lineSeries" 
      :xAxis="lineXAxis" 
      height="300px" 
    />
    
    <PieChart 
      :data="pieData" 
      height="300px" 
    />
  </div>
</template>

<script setup>
import BarChart from '@/components/BarChart.vue';
import LineChart from '@/components/LineChart.vue';
import PieChart from '@/components/PieChart.vue';

const barData = [120, 200, 150, 80, 70, 110, 130];
const barXAxis = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

const lineSeries = [
  { name: 'Email', data: [120, 132, 101, 134, 90, 230, 210] },
  { name: 'Union Ads', data: [220, 182, 191, 234, 290, 330, 310] }
];
const lineXAxis = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

const pieData = [
  { value: 1048, name: 'Search Engine' },
  { value: 735, name: 'Direct' },
  { value: 580, name: 'Email' }
];
</script>

<style scoped>
.chart-container {
  display: grid;
  gap: 20px;
  padding: 20px;
}
</style>

高级功能扩展

在基础组件中添加主题和自定义功能:

<script setup>
// 在ECharts.vue中扩展
import { ref, onMounted, watch } from 'vue';
import * as echarts from 'echarts';

const props = defineProps({
  // ...原有props
  theme: { type: String, default: '' },
  initOptions: Object,
  loading: Boolean,
  loadingOptions: Object
});

// 初始化时添加主题
const initChart = () => {
  if (chartRef.value) {
    chartInstance = echarts.init(
      chartRef.value,
      props.theme,
      props.initOptions
    );
    props.options && chartInstance.setOption(props.options);
    props.loading && chartInstance.showLoading(props.loadingOptions);
  }
};

// 添加loading状态监听
watch(() => props.loading, (val) => {
  if (chartInstance) {
    val ? 
      chartInstance.showLoading(props.loadingOptions) :
      chartInstance.hideLoading();
  }
});
</script>

注意事项

  1. 所有图表组件都需要响应式容器,确保父容器有明确尺寸
  2. 大数据量时建议开启dataZoom或使用large模式
  3. 动态更新数据时,建议使用notMerge: false参数保持平滑过渡
  4. 多图表页面建议使用resize-observer-polyfill处理容器尺寸变化

以上方案提供了Vue 3中ECharts的完整实现路径,从基础封装到具体图表组件的开发,可根据实际需求进一步扩展功能。


网站公告

今日签到

点亮在社区的每一天
去签到