在各种后台管理系统中,我们经常会有很多页面的table表格用来进行数据的搜索和展示。然而很多时候都是重复的操作,我们经常是各种复制粘贴,导致代码逻辑看着虽然挺清晰的,但重复代码很多,而且html结构过于臃肿,很多时候都找不到自己想要的东西。
一、过去的写法
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
</el-table>
类似这样,当然正常情况为了布局经常会有嵌套el-row el-col或者中间的各种插槽方法,这样虽然功能没啥问题,但不得不说,很臃肿,特别是字段很多的时候。(相信写过的人都深有体会)
这时候我们其实稍微变通一下,这些基本都是绑定参数和显示参数,那么何不用循环来写呢。
二、表格的变形记
<el-table :data="tableData" style="width: 100%">
<el-table-column
v-for="(item,index) in tableFileds"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width"
:type="item.type"
/>
</el-table>
这个时候已经满足了简单的显示要求,但是明显,这是不够的,因为我们肯定会在有些地方进行数据操作,或者特殊操作,那么我们稍微来更改一下
<el-table :data="tableData" style="width: 100%">
<el-table-column
v-for="(item,index) in tableFileds"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width"
:type="item.type"
>
<template #default="scope">
<span v-if="item.formater"
{{ item.formater(scope.row) }}
</span>
<span v-else>{{ scope.row[item.prop] }}</span>
</template>
</el-table-column>
</el-table>
这时候基本就满足大多数情况了,循环的tableFileds配置如下
const TABLECOLUMN = [
{
label: '项目1',
prop: 'list1',
width: 80,
}, {
label: '项目2',
prop: 'list2',
width: 80,
},
{
label: '项目3',
prop: 'list3',
width: 80,
// row为当前行的数据
formater:(row)=>{return xxxxxx}
},
{
label: '项目4',
prop: 'list4',
width: 80,
},
{
label: '项目5',
prop: 'list5',
width: 80,
},
];
这样我们把表格的渲染单独放一个文件中,再引入过去使用,页面是不是就清爽了很多,思路也很清晰,当然,这个肯定也没法面面俱到,还有很多场景,比如表格中加输入框之类的,那么
<template #default="scope">
<span v-if="item.formater"
{{ item.formater(scope.row) }}
</span>
<span v-else-if="item.prop === xxxxx">
<el-input v-model="scope.row.xxxx" />
</span>
<span v-else>{{ scope.row[item.prop] }}</span>
</template>
具体使用看实际情况而定,这就已经优化很多了,那么还能不能优化呢,当然能,我们可以对表格进行二次封装,当然,要封装就肯定要面面俱到,这个根据各位的实际业务来,我就简单给各位大略看一下我怎么封装的,仅做参考
<el-table
ref="elTable"
v-loading="loading"
:header-row-style="defaultHeaderRowStyle"
:header-cell-style="defaultHeaderCellStyle"
:cell-style="defaultCellStyle"
v-bind="$attrs"
class="dm-table__main"
>
<template #empty>
<el-empty description="暂无数据" />
</template>
<el-table-column
v-for="field in columns"
:key="field.prop"
v-bind="field"
>
<template
v-if="$slots[field.prop]"
#default="scope"
>
<slot
:name="field.prop"
:row="scope.row"
/>
</template>
<template
v-else-if="transformation && !field.type"
#default="scope"
>
<div>
{{ transformation(scope.row[field.prop]) ?? scope.row[field.prop] }}
</div>
</template>
</el-table-column>
</el-table>
这样封装之后,全局进行组件绑定,最终,我的表格页面变成了
<minTable
:loading="loading.getTableData"
:data="tableData"
:columns="TABLECOLUMN"
>
<template #groupName="{row}">
<el-input v-model="row.groupName" />
</template>
<template #action="{row}">
<nh-button type="text" @click.stop="handleEdit(row)">
编辑
</nh-button>
</template>
</minTable>
const TABLECOLUMN = [{
label: '序号',
type: 'index',
width: 50,
}, {
label: '生效时间',
prop: 'workTime',
minWidth: 320,
formatter: ({ workTime}) => timeFormat(workTime),
}, {
label: '班次名称',
prop: 'groupName',
minWidth: 120,
}, {
label: '计划总人数',
prop: 'planTotalNum',
minWidth: 120,
}, {
label: '班组说明',
prop: 'remark',
minWidth: 120,
}, {
label: '操作',
prop: 'action',
fixed: 'right',
width: 220,
}];
这样,不管多少个表格,我都只需要用组件+一个配置文件就成功把表格渲染出来了,妈妈再也不用担心我维护时寻寻觅觅寻不到自己想要的东西了,也不用担心每次写个什么东西滑轮上上下下滑不到底了。
代码示例基于VUE3,用VUE2的同学请灵性更换插槽的使用