vue3 element plus el-table封装(三)
上文是对el-table的基本封装上增加slot插槽,并且对col插槽进行拓展,本文主要时增加分页组件,同时进行slot传递
//BaseTable.vue没有变
<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 attrs = useAttrs();
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>
//CustomTable.vue增加空表格插槽,分页组件,slot传递,必要时可以扩展多个CustomTable组件
<template>
<BaseTable
v-bind="tableAttrs"
>
<template #empty>
empty
</template>
<!--slots传递 -->
<template v-for="name in Object.keys(slots)" :key="name" #[name]="scope" >
<slot :name="name" v-bind="scope"></slot>
</template>
</BaseTable>
<el-pagination class="page" v-if="attrs.page" v-bind="page" />
</template>
<script lang="ts" setup>
import BaseTable from "./BaseTable.vue";
const attrs = useAttrs();
const slots = useSlots();
const tableAttrs = computed(() => {
const ret = {};
Object.keys(attrs)
.filter((attr) => attr !== "page")
.map((attr) => (ret[attr] = attrs[attr]));
return ret;
});
// 提供分页默认值
const page = computed(() => {
return attrs.page
? {
...attrs.page,
// "current-page": 1, //如果传入了 current-page,必须监听 current-page 变更的事件(@update:current-page)
// "page-size":20, //如果传入了 page-size,且布局包含 page-size 选择器(即 layout 包含 sizes),必须监听 page-size 变更的事件(@update:page-size),否则分页大小的变化将不起作用。
"page-sizes": attrs.page.pageSizes??[10, 20, 30, 40],
layout:attrs.page.layout??"total, sizes, prev, pager, next, jumper",
total: attrs.page.total??0,
}
: null;
});
</script>
<style>
.page{
display: flex;
justify-content: center;
}
</style>
// index.vue
<template>
<CustomTable
:config="config"
:data="tableData"
:style="{ width: '800px' }"
:page="true"
>
<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>
</CustomTable>
</template>
<script lang="ts" setup>
import CustomTable from "./CustomTable.vue";
const config = ref([
{
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>
如果分页组件使用默认值,绑定true即可,如果需要自定义,绑定对象