elementUI el-table 二次封装

351 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

elementUI el-table 二次封装

基本能满足绝大部分的需求,利用el-table预留的插槽,在默认插槽和header插槽里面又分别放了插槽,十分灵活,表头和表格内容全部可以自定义,添加的属性不够可以自己加。另外,Table Attributes 和 Table Events 可以直接写在WsTable标签内,降低与业务的耦合。

展示效果: 在这里插入图片描述

代码示例: 公共组件(定义为WsTable)

<template>
  <el-table
    ref="WsTable"
    :row-key="getRowKey"
    :data="tableData"
    v-bind="$attrs"
    v-on="$listeners"
  >
    <el-table-column
      v-if="showSelect"
      width="50"
      type="selection"
      reserve-selection
    ></el-table-column>
    <el-table-column
      v-if="showIndex"
      fixed
      label="序号"
      width="50"
      type="index"
      :align="align"
    ></el-table-column>
    <el-table-column
      v-for="(col, index) in tableColumns"
      :key="col.prop"
      :prop="col.label"
      :width="col.width"
      :align="col.align || align"
      :fixed="col.fixed"
      :sortable="col.sortable"
      :show-overflow-tooltip="col.showOverflowTooltip"
    >
      <template #header="scope">
        <slot :name="col.header" :scope="{ header: col.label, ...scope }">
          <span>{{ col.label }}</span>
        </slot>
      </template>
      <template #default="scope">
        <slot :name="col.prop" :scope="scope">
          <span>{{ scope.row[col.prop] }}</span>
        </slot>
      </template>
    </el-table-column>

    // 分页组件插槽
    <slot v-show="tableData.length > 10" name="pagination"></slot>
  </el-table>
</template>
<script>
export default {
  name: "WsTable",
  inheritAttrs: false,
  props: {
    // 表格数据
    tableData: {
      type: Array,
      default: () => [],
      require: true,
    },
    // 表格列和列属性:
    // label显示的标题
    // align对齐方式
    // show-overflow-tooltip当内容过长被隐藏时显示tooltip
    tableColumns: {
      type: Array,
      default: () => [],
      require: true,
    },
    // 是否显示多选框
    showSelect: {
      type: Boolean,
      default: false,
    },
    // 是否显示索引
    showIndex: {
      type: Boolean,
      default: false,
    },
    // 对齐方式
    align: {
      type: String,
      default: "center",
    },
    // 行数据的 Key,用来优化 Table 的渲染
    rowKey: {
      type: String,
      default: "id",
    },
  },
  methods: {
    getRowKey(row) {
      return row[this.rowKey];
    },
    // 请求完接口想清空表格所选
    clearSelection() {
      this.$refs.WsTable.clearSelection();
    },
    // 对 Table 进行重新布局
    doLayout() {
      this.$refs.WsTable.doLayout();
    },
  },
};
</script>

<style></style>

父组件

<template>
  <div id="app">
    <WsTable
      :table-data="tableData"
      :table-columns="tableColumns"
      show-select
      show-index
      @selection-change="selectionChange"
    >
      <template #genderHeader="{ scope }">
        <div>
          {{ scope.header }}
          <div>
            <el-select v-model="region" size="mini" placeholder="请选择性别">
              <el-option label="男" value="1"></el-option>
              <el-option label="女" value="2"></el-option>
              <el-option label="未知" value="3"></el-option>
            </el-select>
          </div>
        </div>
      </template>
      <template #gender="{ scope }">
        <div>
          {{
            +scope.row.gender === 1
              ? "男"
              : +scope.row.gender === 2
              ? "女"
              : "未知"
          }}
        </div>
      </template>
      <template #operation>
        <div>
          <el-button>编辑</el-button>
          <el-button>删除</el-button>
        </div>
      </template>
    </WsTable>
  </div>
</template>

<script>
import WsTable from "./components/WsTable.vue";

export default {
  name: "App",
  components: {
    WsTable,
  },
  data() {
    return {
      region: "",
      tableData: [
        {
          name: "张三张三张三张三张三张三张三张三张三张三张三张三张三",
          age: 18,
          gender: "1",
        },
        {
          name: "李四",
          age: 19,
          gender: "2",
        },
        {
          name: "王五",
          age: 20,
          gender: "3",
        },
      ],
      tableColumns: [
        {
          label: "名称",
          prop: "name",
          propHeader: "nameHeader",
          showOverflowTooltip: true,
        },
        {
          label: "年龄",
          prop: "age",
          header: "ageHeader",
          sortable: true,
          width: 100,
        },
        { label: "性别", prop: "gender", header: "genderHeader", width: 1000 },
        {
          label: "操作",
          prop: "operation",
          header: "operationHeader",
          fixed: "right",
          width: 200,
        },
      ],
    };
  },
  methods: {
    selectionChange(selection) {
      console.log('selection', selection)
    }
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

<style scoped>
#app >>> .el-select .el-input__inner {
  text-align: center;
}
</style>