Vue 3项目中引用ECharts并设计多种图表组件的实现方案
以下是一个完整的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({// ...原有propstheme: { 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>
注意事项
- 所有图表组件都需要响应式容器,确保父容器有明确尺寸
- 大数据量时建议开启
dataZoom
或使用large
模式 - 动态更新数据时,建议使用
notMerge: false
参数保持平滑过渡 - 多图表页面建议使用
resize-observer-polyfill
处理容器尺寸变化
以上方案提供了Vue 3中ECharts的完整实现路径,从基础封装到具体图表组件的开发,可根据实际需求进一步扩展功能。