el-table是elementUI中的表格组件,在后台把管理系统中,也是一个比较常用的组件,目前有一个比较好的开源项目ProTable,这个项目做的很好,集成了搜索,表格,分页器功能很强大。但在我的实际使用中也有一些需要更改的地方,因此,我也尝试着封装自己的table组件。
需求
- 定制化:这是最基本的要求,每个表格的表头都是不一样的,封装table组件,首先就要满足它的定制化输入。
- 表格操作列
- 末尾添加一行
制作
定制化
让用户能够自定义配置列表项
思路
父子通信,将父组件配置好的columns传递给子组件,然后使用v-for遍历生成表格cell。
实现
首先我们需要在父组件得到传递过来的参数,使用defineProps接收
typescript
const props = defineProps({
data: {
type: Array,
default: () => []
},
config: {
type: Object,
default: () => ({})
}
})
在这里data的就是将来我们接收tabledata的,config则用来接收columns配置
将接收到的数据进行渲染
html
<el-table-column v-for="(item, index) in config.columns" :key="index" :label="item.label" :width="item.width">
<template #default="{ row }">
<el-input class="inputBox" v-if="item.type === 'txt'" v-model="row[item.prop]" />
</template>
</el-table-column>
似乎这样,就封装好了一个表格组件,但是实际使用中一点代码提示都没有,我们根本不知道需要组件预留的方法,我们似乎都没怎么使用到TS,因此我们来改造一下代码,为config添加一个config配置文件
typescript
type Type = "txt" | "tag";
export interface TableColumns<U> {
type: Type;
prop: keyof U;
label: string;
width?: number;
}
export interface TableConfigTest<T> {
columns: TableColumns<T>[];
}
在这个配置文件中声明了两个TS接口,明确columns该怎么写,并且需要接收一个参数,将来使用组件时,将tabledata的类型接口传进来,就会自动解析prop(使用keyof实现,keyof
是 TypeScript 中的一个关键字,用于获取某个类型的所有属性名组成的联合类型)。
现在来重写一下congig,使用类型断言缩小config的类型
typescript
config: {
type: Object as PropType<TableConfigTest<Object | any>>,
default: () => ({})
}
这样我们就完成组件的第一个需求,定制化。
表格操作列
因为我只需要一个删除行的操作,所以这里使用了一个简单的方法,就是在组件中直接书写操作
html
<el-table-column fixed="right" label="操作" width="120">
<template #default="{ row }">
<el-button type="danger" icon="el-icon-delete" @click="deleteRow(row)"> 删除 </el-button>
</template>
</el-table-column>
然后将删除方法实现
typescript
const deleteRow = (row: any) => {
const index = props.data.indexOf(row);
if (index > -1) {
props.data.splice(index, 1);
}
};
使用演示
html
<MyTable :config="tableConfigEdu" :data="tableDataEdu" :border="true" />
<script setup lang="ts">
interface TableDataTrain {
startDate: string;
endDate: string;
address: string;
content: string;
}
const tableConfigTrain = ref<TableConfigTest<TableDataTrain>>({
columns: [
{
type: "txt",
prop: "startDate",
label: "开始日期",
width: 200
},
{
type: "txt",
prop: "endDate",
label: "截止日期",
width: 200
},
{
type: "txt",
prop: "address",
label: "地点"
},
{
type: "txt",
prop: "content",
label: "内容"
}
]
});
const tableDataTrain = ref<TableDataTrain[]>([{ startDate: "", endDate: "", address: "", content: "" }]);
</script>
封装组件是为了更好的工作,随着工作的需求增加,会不断增加组件的功能,同时也会更新文档。