一、引入ECharts到Vue项目的三种方式
1. 全局引入(适合项目频繁使用)
import Vue from 'vue';
import * as echarts from 'echarts';
Vue.prototype.$echarts = echarts;
2. 局部引入(按需加载,推荐)
<template>
<div ref="chartContainer" style="width: 100%; height: 400px;"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
mounted() {
const chart = echarts.init(this.$refs.chartContainer);
chart.setOption(option);
}
}
</script>
3. 按需引入(体积优化)
import echarts from 'echarts/lib/echarts';
import 'echarts/lib/chart/line';
import 'echarts/lib/chart/bar';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/legend';
二、封装ECharts组件(可复用方案)
基础组件封装
<template>
<div ref="chartRef" :style="{ width, height }"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
props: {
option: { type: Object, required: true },
width: { type: String, default: '100%' },
height: { type: String, default: '400px' }
},
data() {
return {
chart: null
};
},
mounted() {
this.initChart();
},
methods: {
initChart() {
this.chart = echarts.init(this.$refs.chartRef);
this.chart.setOption(this.option);
window.addEventListener('resize', this.resizeChart);
},
resizeChart() {
this.chart && this.chart.resize();
}
},
watch: {
option: {
deep: true,
handler(newVal) {
this.chart && this.chart.setOption(newVal);
}
}
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeChart);
this.chart && this.chart.dispose();
}
};
</script>
使用封装组件
<template>
<div>
<ECharts :option="chartOption" />
</div>
</template>
<script>
import ECharts from '@/components/ECharts.vue';
export default {
components: { ECharts },
data() {
return {
chartOption: {
xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
yAxis: { type: 'value' },
series: [{ data: [820, 932, 901], type: 'bar' }]
}
};
}
};
</script>
三、Vue3组合式API(Composition API)用法
<template>
<div ref="chartRef" style="width: 100%; height: 400px;"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts';
const chartRef = ref(null);
const chart = ref(null);
const props = defineProps({
option: { type: Object, required: true }
});
const initChart = () => {
chart.value = echarts.init(chartRef.value);
chart.value.setOption(props.option);
const resizeHandler = () => {
chart.value && chart.value.resize();
};
window.addEventListener('resize', resizeHandler);
chartRef.value.resizeHandler = resizeHandler;
};
onMounted(() => {
initChart();
});
watch(
() => props.option,
(newVal) => {
chart.value && chart.value.setOption(newVal);
},
{ deep: true }
);
onUnmounted(() => {
if (chartRef.value.resizeHandler) {
window.removeEventListener('resize', chartRef.value.resizeHandler);
}
chart.value && chart.value.dispose();
});
</script>
四、性能优化与注意事项
1. 避免重复渲染
<template>
<div v-if="showChart">
<ECharts :option="chartOption" />
</div>
</template>
2. 按需加载主题
import darkTheme from 'echarts/theme/dark';
echarts.registerTheme('dark', darkTheme);
const chart = echarts.init(this.$refs.chartContainer, 'dark');
3. 处理大数据量
chart.setOption({
series: [{
type: 'line',
progressive: 1000,
data: largeDataArray
}]
});
五、问题
1. 问:Vue中ECharts的生命周期管理要点?
- 答:
- mounted:初始化图表并设置option;
- watch:监听option变化,动态更新图表;
- beforeDestroy/beforeUnmount:移除resize监听,销毁图表实例释放内存。
2. 问:如何优化ECharts在Vue中的性能?
- 答:
- 按需引入ECharts模块,减小打包体积;
- 使用
v-if
控制非必要图表渲染;
- 大数据场景启用
progressive
或dataZoom
;
- 窗口resize时使用节流函数(如
lodash.throttle
)避免频繁重绘。
3. 问:ECharts组件如何响应父组件数据变化?
- 答:
- 通过
watch
监听props变化,调用chart.setOption(newVal)
更新图表;
- 若数据量庞大,可通过
chart.setOption(newVal, true)
强制清空并重绘。
六、总结
- 引入方式:优先局部引入,按需加载模块;
- 组件封装:将ECharts封装为可复用组件,管理好生命周期;
- 响应式处理:监听窗口resize并调用
chart.resize()
;
- 性能优化:避免重复渲染,合理配置ECharts参数。