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