上文是对el-table的基本封装,只能满足最简单的应用,本文主要是在上文的基础上增加slot插槽,并且对col插槽进行拓展,增加通用性
// BaseTable.vue
js
<template>
<el-table>
<template v-for="name in tableSlots" :key="name" #[name]>
<slot :name="name"></slot>
</template>
<el-table-column v-for="(col,index) in $attrs.config" :key="index" v-bind="col">
<template v-if="col.slot" #[getColSlot(col)]="scope" >
<slot :name="col.slot" v-bind="scope"></slot>
</template>
</el-table-column>
</el-table>
</template>
<script lang="ts" setup>
const slots=useSlots();
const tableSlots=computed(()=>{
// 原生el-table插槽只有default,append,empty
// 原生el-table-column插槽只有table插槽只有default,header
// 这里将header单独处理,认为是col的插槽,从table插槽中排除
return Object.keys(slots).filter(name=>name!=='header')
})
const getColSlot=(col)=>{
return col.slot==='header'?'header':'default'
}
</script>
js
<template>
<BaseTable :config="config" :data="tableData" :style="{width:'800px'}">
<template #status="scope">
<el-text :type="scope.row.status.type ">{{ scope.row.status.content }}</el-text>
</template>
<template #btn="scope">
<el-button type="primary">{{ scope.row.btn }}</el-button>
</template>
<!-- 如有多个类似slot,也可以用如下方式渲染 -->
<!-- <template v-for="(col,index) in config.filter(item=>item.slot && item.slot!=='header')" :key="index" #[col.slot]="scope">
<el-button type="primary">{{ scope.row.btn }}</el-button>
</template> -->
<template #header="scope">
<el-button type="primary">{{ scope.column.label }}</el-button>
</template>
</BaseTable>
</template>
<script lang="ts" setup>
import BaseTable from './BaseTable.vue'
const config=[
{
type:'selection'
},
{
prop: 'date',
label:'日期',
width:'180'
},
{
prop: 'name',
label:'姓名',
},
{
prop: 'status',
label:'状态',
slot:'status',
width:'180'
},
{
prop: 'btn',
label:'操作',
slot:'btn',
width:'180'
},
{
prop: 'header',
label:'按钮header',
slot:'header',
width:'180'
},
];
const tableData = [
{
date: '2016-05-03',
name: '张三',
status:{content:'工作',type:'success'},
btn: 'confirm',
},
{
date: '2016-05-02',
name: '李四',
status:{content:'出差',type:'primary'},
btn: 'confirm',
},
{
date: '2016-05-04',
name: '王五',
status:{content:'休假',type:'danger'},
btn: 'confirm',
},
]
</script>
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/dad5e7be52c84c12997da0829cdf9178.png)