ECharts 是一个用于可视化数据的图表库,支持多种图表类型,比如折线图、柱状图、饼图等。其文档详尽,使用简单,在数据可视化领域广泛应用。
本文将从结构理解、封装、数据对接与最终使用四个方面,介绍如何在 Vue3 项目中优雅地使用 ECharts。
一、ECharts 的基本结构
ECharts 的使用分为三个核心步骤:
-
准备 DOM:创建图表要挂载的 DOM 节点;
-
初始化实例:基于该 DOM 创建 ECharts 实例;
-
设置数据 :调用
setOption
方法绘制数据图表。
实际上,我们的封装思路也正是基于以上流程进行的。
二、封装 useChart 组合函数
typescript
// useChart.ts
import { markRaw, onBeforeUnmount, onMounted, type Ref } from 'vue'
import { ref } from 'vue'
import * as echarts from 'echarts'
export function useChart(chartRef: Ref<HTMLElement | null>, setChartData: () => Promise<any>) {
const chartInstance = ref<echarts.ECharts | null>(null)
const initChart = async () => {
if (chartRef.value) {
// 初始化图表,并使用 markRaw 取消响应式,避免 resize 异常
chartInstance.value = markRaw(echarts.init(chartRef.value))
const options = await setChartData()
chartInstance.value.setOption(options)
}
}
// 自动响应窗口变化
const resizeChart = () => {
chartInstance.value?.resize()
}
onMounted(() => {
initChart()
window.addEventListener('resize', resizeChart)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeChart)
chartInstance.value?.dispose()
})
}
说明
-
chartRef
:绑定图表 DOM 的ref
。 -
setChartData
:用于返回图表配置项的函数,通常会包含接口数据处理。
三、图表数据的准备
1. 定义基础模板
php
const setChartData = async () => {
const chartOptions = reactive({
title: { text: '用电统计' },
tooltip: { trigger: 'axis' },
legend: { data: [] },
xAxis: {
type: 'category',
boundaryGap: false,
data: ['13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00','20:00','21:00']
},
yAxis: {
type: 'value',
min: 0,
max: 200,
interval: 20,
axisLabel: { formatter: '{value} KW' }
},
series: [
{ name: '', type: 'line', smooth: true, data: [], markPoint: { data: [{ type: 'max', name: 'Max' }, { type: 'min', name: 'Min' }] } },
{ name: '', type: 'line', smooth: true, data: [], markPoint: { data: [{ type: 'max', name: 'Max' }, { type: 'min', name: 'Min' }] } },
{ name: '', type: 'line', smooth: true, data: [], markPoint: { data: [{ type: 'max', name: 'Max' }, { type: 'min', name: 'Min' }] } }
]
})
// 模拟请求接口
const res = await chartDataApi()
chartOptions.legend.data = res.data.list.map((item: any) => item.name)
for (let i = 0; i < res.data.list.length; i++) {
chartOptions.series[i].name = res.data.list[i].name
chartOptions.series[i].data = res.data.list[i].data
}
return chartOptions
}
2. 模拟接口数据结构
css
// 接口返回结构
{
code: 200,
message: "操作成功",
data: {
list: [
{ name: "设备A", data: [201, 501, 301, 70, 601, 80, 401, 60, 50] },
{ name: "设备B", data: [401, 601, 501, 80, 701, 90, 601, 70, 80] },
{ name: "设备C", data: [301, 401, 601, 50, 701, 20, 301, 40, 60] }
]
}
}
四、在组件中使用图表
1. 模板中挂载 DOM
xml
<template>
<div ref="chart1" class="chart"></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useChart } from '@/composables/useChart'
import { setChartData } from '@/api/chart'
const chart1 = ref<HTMLElement | null>(null)
useChart(chart1, setChartData)
</script>
问:为什么组件中不需要再写 onMounted
? 答:这是 组合函数共享组件上下文 的特性。在 useChart
内部调用了 onMounted()
,Vue 会自动将它注册到当前使用该组合函数的组件生命周期中。如果在组件的 onMounted()
调用 useChart
。那 useChart
中可以不写onMounted()
欢迎大家留言探讨你们的实践经验,如有疏漏或不妥之处,欢迎在评论区指出,互相学习,共同进步!