基于 Element Plus 的 TableColumnGroup 组件使用说明
在前端开发中,表格是展示数据的常用组件,而复杂的业务场景往往需要用到多级表头。本文将介绍一款基于 Element Plus 封装的 TableColumnGroup 组件,该组件支持嵌套列组、自定义渲染、条件渲染等功能,能满足大多数复杂表格的展示需求。
组件功能特点
- 支持多级嵌套列组,轻松实现复杂表头结构
- 提供灵活的单元格渲染方式:默认渲染、自定义组件渲染、条件渲染
- 支持表格列的固定、宽度设置、对齐方式配置
- 内置数字格式化功能,支持千分制显示和单位转换
- 支持自定义样式类名,方便进行样式调整
组件参数说明
参数名 | 类型 | 默认值 | 说明 |
label | String | - | 列组的标题 |
type | String | '' | 列的类型,同 Element Plus 的 el-table-column |
className | String | - | 列组的样式类名 |
columns | Array | [] | 普通列配置数组,当没有嵌套列组时使用 |
nestedGroups | Array | [] | 嵌套列组配置数组 |
groupFixed | String/Boolean | null | 列组是否固定,同 Element Plus 的 fixed 属性 |
groupWidth | String/Number | - | 列组的宽度 |
groupProp | String | - | 列组对应的属性名 |
treeProps | Object | null | 树形表格配置 |
rowKey | String | - | 行数据的唯一标识 |
columns 数组元素配置
columns 数组中的每个元素可配置以下属性:
属性名 | 类型 | 说明 |
align | String | 单元格内容对齐方式,默认 'center' |
label | String | 列标题 |
prop | String | 对应行数据的属性名 |
width | String/Number | 列宽度 |
className | String | 列的样式类名,默认使用父组件的 className |
fixed | String/Boolean | 列是否固定 |
customRender | Component | 自定义渲染组件 |
customRenderProps | Object | 传递给自定义渲染组件的属性 |
conditionalRender | Function | 条件渲染函数,返回布尔值决定是否显示内容 |
unit | String | 数据单位,用于格式化显示 |
使用示例
1. 基础使用(普通列)
<template><el-table :data="tableData"><TableColumnGroup :columns="[{ label: '姓名', prop: 'name' },{ label: '年龄', prop: 'age', unit: '岁' },{ label: '邮箱', prop: 'email' }]"/></el-table>
</template>2. 嵌套列组
<template><el-table :data="tableData"><TableColumnGroup label="基本信息"><TableColumnGroup :columns="[{ label: '姓名', prop: 'name' },{ label: '年龄', prop: 'age', unit: '岁' }]"/></TableColumnGroup><TableColumnGroup label="联系方式"><TableColumnGroup :nestedGroups="[{label: '电话',columns: [{ label: '手机', prop: 'phone' },{ label: '座机', prop: 'landline' }]},{label: '网络',columns: [{ label: '邮箱', prop: 'email' },{ label: '网址', prop: 'website' }]}]"/></TableColumnGroup></el-table>
</template>3. 自定义渲染
<template><el-table :data="tableData"><TableColumnGroup :columns="[{ label: '姓名', prop: 'name' },{ label: '状态', prop: 'status',customRender: StatusTag,customRenderProps: { colors: { active: 'green', inactive: 'gray' } }}]"/></el-table>
</template><script setup>
import StatusTag from './StatusTag.vue'
</script>4. 条件渲染
<template><el-table :data="tableData"><TableColumnGroup :columns="[{ label: '姓名', prop: 'name' },{ label: '业绩', prop: 'performance',unit: '元',conditionalRender: (row) => row.performance > 0}]"/></el-table>
</template>完整代码实例
<!-- TableColumnGroup.vue -->
<template><el-table-column align="center" :label="label" :type="type" :class-name="className" :fixed="groupFixed":width="groupWidth" :prop="groupProp"><!-- 支持嵌套列组 --><template v-if="hasNestedGroups"><TableColumnGroup v-for="(nestedGroup, nestedIndex) in nestedGroups" :key="nestedIndex" v-bind="nestedGroup" /></template><!-- 普通列 --><template v-else><el-table-column v-for="col in columns" :key="col.prop" :align="col.align || 'center'" :label="col.label":prop="col.prop" :width="col.width" :class-name="col.className || className" :fixed="col.fixed"><template #default="scope"><span><!-- 支持自定义渲染 --><template v-if="col.customRender"><component :is="col.customRender" :row="scope.row" :value="scope.row[col.prop]"v-bind="col.customRenderProps" /></template><template v-else-if="col.conditionalRender"><!-- 条件渲染 --><span v-if="col.conditionalRender(scope.row)">{{ formatNumberWithUnit(scope.row[col.prop], col.unit) }}</span><span v-else class="hidden-column">-</span></template><template v-else><!-- 数字类型格式化:千分制+两位小数 -->{{ formatNumberWithUnit(scope.row[col.prop], col.unit) }}</template></span></template></el-table-column></template></el-table-column>
</template><script setup>
import { computed } from 'vue'
import { formatNumberWithUnit } from '@/utils/validate'const props = defineProps({label: String,type: {type: String,default: '',},className: String,// 普通列配置columns: {type: Array,default: () => [],},// 嵌套列组配置nestedGroups: {type: Array,default: () => [],},groupFixed: {type: [String, Boolean],default: null,},groupWidth: [String, Number],groupProp: String,// 树形表格配置treeProps: {type: Object,default: null,},rowKey: String,
})// 判断是否有嵌套列组
const hasNestedGroups = computed(() => {return props.nestedGroups && props.nestedGroups.length > 0
})
</script><style lang="scss">
.el-table__row.level-1 {background-color: #ffffff !important;
}.el-table__row.level-2 {background-color: #f8f3c3 !important;
}.el-table__row.level-3 {background-color: #fcd787 !important;
}.el-table__row:hover>td {background-color: #e9e9e9 !important;
}.hidden-column {color: #ccc;font-style: italic;
}
</style>
模板使用
<el-table v-loading="loading" :data="oaBusinessMetricList" border max-height="660" row-key="id"scrollbar-always-on :fit="true" resizable @selection-change="handleSelectionChange"><el-table-column align="center" type="selection" width="55" fixed="left" /><!-- 使用 TableColumnGroup 组件渲染列组 --><TableColumnGroup v-for="group in columnGroups" :key="group.key" v-bind="group" /><!-- 操作列 --><el-table-column align="center" class-name="small-padding fixed-width blueInfoHeader" fixed="right" label="操作"width="120"><template #default="scope"><el-tooltip content="修改" placement="top"><el-button v-hasPerm="['oa:oaBusinessMetric:edit']" icon="Edit" link type="primary"@click="handleUpdate(scope.row)" /></el-tooltip></template></el-table-column></el-table>
const {getColumns,getColumnGroups,
} = useOaBusinessMetric();// 获取列组配置并生成列组数据
const columnGroups = computed(() =>getColumnGroups.value.map(group => ({...group,columns: getColumns(group.columnKey)}))
);样式说明
组件内置了一些基础样式,可通过自定义类名进行覆盖:
- 不同层级行的背景色:.el-table__row.level-1、.el-table__row.level-2、.el-table__row.level-3
- 行 hover 样式:.el-table__row:hover>td
- 条件渲染隐藏时的样式:.hidden-column(灰色斜体)
可根据实际需求在项目中自定义这些样式类。
总结
TableColumnGroup 组件通过对 Element Plus 的 el-table-column 进行二次封装,提供了更强大的列组管理功能,特别适合需要展示复杂表头结构的业务场景。组件设计灵活,支持多种渲染方式,能够满足不同的数据展示需求。
希望本文能帮助大家更好地理解和使用这个组件,如有任何问题或建议,欢迎在评论区留言讨论。

