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即可,如果需要自定义,绑定对象
在这里插入图片描述