在中后台管理系统开发中,表格展示是高频需求,重复编写el-table和el-table-column不仅效率低下,还会导致代码冗余。本文将结合实际项目代码,从配置化思想出发,详解如何封装通用的CustomTable组件,并通过配置文件解耦表格结构,实现高效复用。
一、项目背景与目录结构
先梳理核心文件的位置和职责:
src/views/Dashboard/tableConfig.js:仪表盘页面的表格、搜索、表单配置文件,集中管理表格列、搜索项、编辑表单的结构化配置;src/views/Message/tableConfig.js:消息页面的表格配置文件,复用相同的配置规范;src/components/CustomTable/index.vue:通用表格组件封装核心文件,接收配置参数并渲染表格。
二、tableConfig配置文件解析
表格的列结构通过tableConfig数组配置化定义,先以Dashboard/tableConfig.js为例分析配置项设计:
1. 核心配置项说明
| 配置字段 | 类型 | 作用 | 示例 |
|---|---|---|---|
prop |
String | 对应接口返回数据的字段名,与el-table-column的prop一致 |
prop: 'projectName' |
label |
String | 表格列的表头文字 | label: '标题' |
formatter |
Function | 列数据格式化函数,接收行数据返回处理后的值 | formatter: (row) => row + '个' |
slot |
Boolean | 是否为自定义插槽列(用于操作按钮等) | slot: true |
slotName |
String | 自定义插槽名称,供父组件传递内容 | slotName: 'handle' |
2. 典型配置示例
javascript
// Dashboard/tableConfig.js
export const tableConfig = [
{
prop: 'projectName',
label: '标题'
},
{
prop: 'createTime',
label: '创建时间'
},
{
prop: 'num',
label: '数量',
formatter: (row) => row + '个' // 数据格式化
},
{
slot: true,
label: '操作',
slotName: 'handle' // 自定义插槽
}
]
配置文件的核心价值是将表格结构与业务页面解耦,后续修改列顺序、新增列、调整格式,只需修改配置数组,无需改动页面和组件代码。
三、Dashboard/index.vue:CustomTable的使用
业务页面中只需引入配置文件,传递表格数据和配置给CustomTable,并通过插槽实现自定义列内容:
vue
<template>
<div class="dashboard-page">
<!-- 通用表格组件 -->
<CustomTable
:tableData="tableData"
:tableConfig="tableConfig"
@handleEdit="handleEdit"
@handleDelete="handleDelete"
>
<!-- 操作列自定义插槽 -->
<template #handle="scope">
<el-button size="small" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
</CustomTable>
</div>
</template>
<script setup>
import { ref } from 'vue'
import CustomTable from '@/components/CustomTable/index.vue'
import { tableConfig } from './tableConfig.js'
// 模拟表格数据(实际从接口获取)
const tableData = ref([
{
projectName: 'XX项目',
createTime: '2024-01-01',
num: 10,
// 其他字段...
}
])
// 编辑事件
const handleEdit = (row) => {
console.log('编辑', row)
}
// 删除事件
const handleDelete = (row) => {
console.log('删除', row)
}
</script>
页面传递给CustomTable的核心参数/方法
| 名称 | 类型 | 作用 |
|---|---|---|
tableData |
Array | 表格渲染的原始数据 |
tableConfig |
Array | 表格列的配置数组(来自tableConfig.js) |
| 自定义事件(如handleEdit) | Function | 父组件定义的业务方法,通过插槽传递给子组件触发 |
四、CustomTable组件核心封装实现
src/components/CustomTable/index.vue是封装核心,核心逻辑是循环tableConfig配置数组,动态渲染el-table-column,同时支持格式化、插槽等扩展能力。
完整代码实现
vue
<template>
<el-table
:data="tableData"
border
stripe
style="width: 100%"
v-bind="$attrs" // 透传el-table的原生属性(如height、size等)
>
<!-- 循环渲染表格列 -->
<template v-for="(item, index) in tableConfig" :key="index">
<!-- 普通列(带格式化) -->
<el-table-column
v-if="!item.slot"
:prop="item.prop"
:label="item.label"
align="center"
>
<template #default="scope">
<!-- 支持数据格式化函数 -->
{{ item.formatter ? item.formatter(scope.row[item.prop]) : scope.row[item.prop] }}
</template>
</el-table-column>
<!-- 插槽列(自定义内容,如操作按钮) -->
<el-table-column
v-else
:label="item.label"
align="center"
>
<template #default="scope">
<slot :name="item.slotName" :row="scope.row"></slot>
</template>
</el-table-column>
</template>
</el-table>
</template>
<script setup>
import { defineProps, useAttrs } from 'vue'
// 定义组件接收的Props
const props = defineProps({
// 表格数据
tableData: {
type: Array,
required: true,
default: () => []
},
// 表格列配置
tableConfig: {
type: Array,
required: true,
default: () => []
}
})
// 透传el-table的原生属性(如max-height、fit等)
const attrs = useAttrs()
</script>
<style scoped>
.el-table {
--el-table-header-text-color: #333;
--el-table-row-hover-bg-color: #f8f9fa;
}
</style>
封装核心要点
1. Props设计
tableData:接收父组件传递的表格数据源,类型为数组且必填;tableConfig:接收列配置数组,与tableConfig.js的结构对应,实现列的动态渲染。
2. 动态渲染列
- 普通列 :判断
item.slot为false时,渲染带prop的常规列,若配置了formatter则执行格式化函数处理数据; - 插槽列 :判断
item.slot为true时,渲染自定义插槽列,通过slotName关联父组件的插槽,同时传递scope.row(行数据)给父组件,满足操作按钮获取行数据的需求。
3. 属性透传
通过v-bind="$attrs"将父组件传递的el-table原生属性(如height、size、max-height等)透传给内部的el-table,提升组件的灵活性。
4. 样式与交互优化
通过scoped样式统一表格的表头文字颜色、行悬浮背景色,保持全局样式一致性。
五、组件复用与扩展
1. 多页面复用
Message/tableConfig.js定义了消息页面的表格配置,只需在Message/index.vue中引入CustomTable和对应的tableConfig,即可快速渲染表格:
vue
<template>
<CustomTable :tableData="messageData" :tableConfig="tableConfig">
<template #detail="scope">
<el-button size="small" @click="viewDetail(scope.row)">查看详情</el-button>
</template>
</CustomTable>
</template>
<script setup>
import CustomTable from '@/components/CustomTable/index.vue'
import { tableConfig } from './tableConfig.js'
// 其他逻辑...
</script>
2. 扩展能力
- 支持更多格式化场景 :如时间格式化、状态枚举转换,只需在
tableConfig中扩展formatter函数; - 支持自定义列宽 :在
tableConfig中新增width字段,渲染时绑定到el-table-column的width属性; - 支持排序/筛选 :在
tableConfig中新增sortable/filters字段,透传给el-table-column。
六、封装价值与总结
1. 核心价值
- 提效降本 :新增表格页面只需编写配置文件和业务逻辑,无需重复编写
el-table和el-table-column; - 易维护:表格结构修改只需调整配置文件,无需改动多个页面;
- 统一规范:所有表格遵循相同的配置规范,团队协作更高效;
- 高扩展性:通过插槽、格式化函数、属性透传,满足不同业务场景的定制化需求。
2. 总结
本文从实际项目出发,讲解了基于配置化思想的CustomTable组件封装流程:通过tableConfig.js集中管理表格列配置,业务页面传递数据和配置给CustomTable,组件内部循环配置动态渲染表格列,并支持格式化、插槽等扩展能力。这种封装方式既符合中后台系统"高复用、易维护"的需求,也体现了Vue组件化开发的核心思想。
Vue3 + Element Plus 实战:通用搜索组件CustomSearch封装与应用