一、前言
后台系统绕不开图表:销量趋势、占比分布、实时监控。本篇用 Vue3 + ECharts 干两件事:按需引入省体积 (077 篇精神)+ 封装 BaseChart 通用组件(一次封装全项目用,resize 自动跟随)。
bash
npm install echarts
二、按需引入:全量 1MB → 按需 300KB
ECharts 全量引入很简单但体积感人;生产用 echarts/core 手动注册需要的模块:
ts
// src/plugins/echarts.ts ------ 统一注册处
import * as echarts from 'echarts/core'
import { BarChart, LineChart, PieChart } from 'echarts/charts' // 图表类型
import {
GridComponent, // 网格(柱状/折线必配)
TooltipComponent, // 提示框
LegendComponent, // 图例
TitleComponent // 标题
} from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers' // 渲染器
echarts.use([
BarChart, LineChart, PieChart,
GridComponent, TooltipComponent, LegendComponent, TitleComponent,
CanvasRenderer
])
export default echarts
用到新图表类型(如 MapChart)时回来加一行注册------忘了注册报"Unknown series xxx",先想到这里查。
三、封装 BaseChart 组件
设计目标:父组件只传 option(配置对象),组件负责 init / 更新 / resize / 销毁:
vue
<!-- src/components/BaseChart.vue -->
<template>
<div ref="chartRef" :style="{ width: '100%', height: height }"></div>
</template>
<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import { useResizeObserver } from '@vueuse/core' // 079 篇
import echarts from '@/plugins/echarts'
import type { EChartsOption } from 'echarts'
const props = withDefaults(
defineProps<{
option: EChartsOption // 图表配置:数据变了图表自动更新
height?: string
}>(),
{ height: '320px' } // ★ 默认高度,容器必须有高度才能渲染
)
const chartRef = ref<HTMLDivElement>()
let chart: echarts.ECharts | null = null // ★ 非响应式:echarts 实例不需要响应式包裹
onMounted(() => {
chart = echarts.init(chartRef.value!)
chart.setOption(props.option)
})
// ★ option 变化 → 更新(notMerge 彻底替换,防止旧系列残留)
watch(
() => props.option,
(newOption) => chart?.setOption(newOption, true),
{ deep: true }
)
// ★ 容器尺寸变化 → 自适应(080 篇最高频需求)
useResizeObserver(chartRef, () => chart?.resize())
// ★ 销毁实例,防内存泄漏
onBeforeUnmount(() => {
chart?.dispose()
chart = null
})
</script>
四个职责对应四个生命周期动作:挂载 init → 数据 watch setOption → 尺寸 resize → 卸载 dispose。
四、完整可运行代码:使用方
vue
<!-- src/views/ChartView.vue -->
<template>
<el-row :gutter="12">
<el-col :span="12">
<BaseChart :option="barOption" height="300px" />
</el-col>
<el-col :span="12">
<BaseChart :option="lineOption" height="300px" />
</el-col>
</el-row>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import BaseChart from '@/components/BaseChart.vue'
import type { EChartsOption } from 'echarts'
// 柱状图:商品销量
const barOption = ref<EChartsOption>({
title: { text: '商品销量 TOP5' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: ['键盘', '鼠标', '耳机', '显示器', '主机'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [320, 280, 210, 180, 120], itemStyle: { color: '#7c3aed' } }]
})
// 折线图:模拟接口返回后更新
const lineOption = ref<EChartsOption>({
title: { text: '访问趋势' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五'] },
yAxis: { type: 'value' },
series: [{ type: 'line', data: [150, 230, 224, 218, 135], smooth: true }]
})
// 模拟:2 秒后接口数据到了,折线图自动更新(watch 生效验证)
setTimeout(() => {
lineOption.value = {
...lineOption.value,
series: [{ type: 'line', data: [90, 110, 160, 240, 300], smooth: true }]
}
}, 2000)
</script>
【截图位置:左右两个图表;2 秒后折线图数据自动刷新】
注意 option 里已包含 title 配置,组件不额外接收 title prop------图表外观全由 option 决定。
五、option 配置从哪来
不需要背配置!三步法:
text
1. 去 echarts 官网 Examples 挑一个长得像的
2. 复制 option 粘到 BaseChart 的 prop 里
3. 改数据、改颜色(itemStyle.color、颜色数组 color 数组)
主题色联动(071 篇):把品牌色抽成常量,ECharts 配置和 CSS 变量用同一份------全站颜色统一。
六、踩坑记录
- 图表不显示、无报错:容器高度为 0(div 默认高度 0)------显式给 height(组件默认 320px 兜底)
- 数据变了图不变 :直接改 option 内部属性但引用没变,或 watch 没开 deep------统一走
watch(() => props.option, ..., { deep: true }) - 切换类型后旧数据残留 :setOption 默认合并模式------第二个参数传
true(notMerge 完全替换) - 窗口拉伸图表不跟:没监听 resize------useResizeObserver 兜底(比 window resize 精准到容器)
- tab 切换回来图表空白:组件在 display:none 时 init,宽高算出来是 0------切换可见后再 init 或手动 resize
- echarts 实例包进 ref :
ref(echarts.init(...))被代理后内部对象行为异常------实例用普通变量存,别做响应式 - Unknown series type: xxx:按需引入漏注册图表类型------去 plugins/echarts.ts 补注册
七、今日小结
- 按需引入:echarts/core + use(...) 注册图表/组件/渲染器,忘了注册就 Unknown series
- BaseChart 四职责:init / setOption(notMerge)/ resize(ResizeObserver)/ dispose
- 实例不做响应式 ;容器必须有高度
- 配置不用背:官网 Examples 抄 + 改数据改色
下篇预告
内容编辑绕不开富文本:公告、文章、商品详情。下一篇 081 富文本编辑器集成 wangEditor 5:Vue3 封装、图片上传配置,以及必踩的销毁坑。