在我们开发业务系统的时候,往往都需要一些数据报表进行统计查看,本篇内容介绍如何在实际的前端中对报表内容进行的一些封装操作,以便提高报表模块开发的效率,报表模块的展示主要是结合Vue3中比较广泛使用的echarts图表组件进行展示。
1、ECharts 图表组件介绍
ECharts 是一款基于 JavaScript 的开源可视化图表库,它非常高效,能够支持大量数据的渲染。与 Vue 3 配合时,ECharts 能够快速响应视图更新,确保报表的平滑渲染和高性能表现。ECharts 提供了多种类型的图表(如折线图、柱状图、饼图、散点图、雷达图等),并且支持多种交互方式(如缩放、提示框、动态数据等)。
Vue 3 提供了强大的组件化开发方式,可以将不同的图表封装成独立的组件,方便维护、重用和组合。每个图表组件可以根据不同的报表需求定制,实现高度复用。
Vue 3 提供了双向绑定和响应式的数据流机制,当 Vue 组件的状态发生变化时,图表可以自动更新。例如,通过绑定数据到 chartOption
,一旦数据变化,ECharts 会自动重新渲染相应的图表。因此我们可以通过动态绑定数据的方式,实现报表模块的图表展示。
ECharts 的官网地址:https://echarts.apache.org/zh/index.html
ECharts 的各种案例地址:https://echarts.apache.org/examples/zh/index.html

我们单击每个具体的图表例子,可以查看对应的数据和形状,根据具体业务的数据和相关设置,替换这些数据就可以了。

2、定义通用图表组件和具体业务图表组件
我们为了方便开发各类型的业务图表,我们可以针对性的对图表类型、折线类型、条状类型图表进行一些简单的封装,以便方便统一使用相关的数据。

上面我在组件目录里面创建了几个不同类型的图表组件,组件主要公布一些props参数来传递,如下说是定义数据的属性。
//声明Props的接口类型
interface Props {
data?: any[]; // 固定列表方式,直接绑定,项目包括id,label属性
}
//使用默认值定义Props
const props = withDefaults(defineProps<Props>(), {
data: () => {
return [];
},
});
然后对data的属性监控,变化的时候,加载图表数据即可。
watch(
() => props.data,
(newValue = []) => {
loadChart(newValue);
},
{ immediate: true } // 可选:如果你希望首次立即触发
);
// 加载图表数据
async function loadChart(res) {
setOptions(
{
tooltip: {
trigger: "item"
},
legend: { //图例设置
orient: "vertical",
right: 'right'
},
series: [
{
name: "标题信息", //图表标题
type: "pie", //图表类型,饼图
radius: "60%",
center: ["30%", "50%"],
data: res, //动态数据
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)"
}
}
}
]
},
{
name: "click",
callback: params => {
console.log("click", params);
}
},
{
type: "zrender",
name: "click",
callback: params => {
console.log("点击空白处", params);
}
}
);
};
而通用图表组件的界面代码比较简单,只需要标记下控件即可,如下代码所示。
<template>
<div ref="pieChartRef" style="width: 100%; height: 35vh" />
</template>
有了简单的组件,我们再次在此基础上,对不同业务表现类型的图表进行更高层次的组件封装,以便可以用在首页或者其他地方,实现多个案例重用显示的处理。
例如,对应统计某个类型的业务图表,如下所示。

对于数据的处理,我们通过接口动态获取图表统计的data数据,如下所示。
// 饼图处理
async function searchPie() {
const data = await report.CarbonSummaryCategory(Number(year.value));
pieData.value = data.map(item => ({
value: item.value,
name: `${item.category} (${item.percentage})`
}));
}
组件封装的时候,我们直接使用前面封装的组件。
import Pie from '@/components/echarts/Pie.vue';
这个业务图表组件,我们为了通用,也需要提供一些属性供外部传入,实现数据的动态化处理,因此通过提供prop的属性方式处理。
//声明Props的接口类型
interface Props {
year?: number | string;
month?: number | string;
stack?: boolean; //是否堆叠
type?: string; //图表类型
showLink?: boolean;
}
//使用默认值定义Props
const props = withDefaults(defineProps<Props>(), {
year: 0,
month: 0,
stack: true,
type: 'bar',
showLink: false,
});
这样组件的处理逻辑代码如下所示。
// 获取当前日期
const currentDate = new Date();
const currentYear = ref(currentDate.getFullYear());
const currentMonth = ref(currentDate.getMonth() + 1); // 月份从0开始,所以加1
// ✅ 在 setup 中补充默认值(只当 props 没传时才使用当前时间)
const year = computed(() => Number(props.year || currentYear.value))
const month = computed(() => Number(props.month || currentMonth.value))
const loading = ref(true);
const barData = ref(); // 折线图数据
const pieData = ref([]); // 饼图数据
//页面初始化加载
onMounted(async () => {
await search();
});
async function search() {
loading.value = true;
await searchPie();
setTimeout(() => {
loading.value = false;
}, 500);
}
// 监听 Props 变化
watch(
() => [props.year, props.month, props.stack, props.type],
async () => {
await search();
}
);
// 饼图处理
async function searchPie() {
const data = await report.CarbonSummaryCategory(Number(year.value));
pieData.value = data.map(item => ({
value: item.value,
name: `${item.category} (${item.percentage})`
}));
}
界面代码处理上,我们使用第一次封装的饼图组件,并通过提供外部卡片的显示封装,使它更加好看一些。如下所示。
<template>
<div class="welcome">
<el-card>
<template #header>
<span style="font-size: 16px; font-weight: 500"> {{ year }} 年碳排放占比 </span>
<div class="float-end" v-if="showLink">
<router-link to="/report/carbon_summary">
<el-link type="primary">查看详细</el-link>
</router-link>
</div>
</template>
<el-skeleton animated :rows="7" :loading="loading">
<template #default>
<Pie :data="pieData" />
</template>
</el-skeleton>
</el-card>
</div>
</template>
其他条状图表、折线图表等其他类型的图表,依次通过这样的处理方式,可以实现业务组件的重用。
如我们可能在首页上放置一些图表组件,具体报表页面上也放置相同的图表组件,这样就可以很好的重用了。

在前端界面开发中,良好的组件封装和使用,可以给我们提供更好的开发效率,因此为了业务的快速开发,我们不仅在代码生成代码的方面持续优化,也在一些前端页面的开发中,提取一些常用的场景组件,最大化的实现代码的快速开发。