Element-ui Table 封装

Element Table

0. 前言

  公司技术选型: vue + element-ui
  后端开发也是用封装的 UI 组件,CSS 样式(你懂得 ~。~)。那就少让人家写HTML、CSS

1. 添加 `columns` 属性,来完成类似 antd 的功能

<template>
  <table-client :data="data" :columns="columns" />
</template>

<script>
export default {
  data() {
    return {
      columns: [
        { type: "selection", align: "center" },
        { type: "index", label: "序号", index: index => index, align: "center" },
        { prop: "date", label: "日期",  align: "center", sortable: true }
      ],
      data: [
        { date: "2016-05-02", name: "王1", address: "金沙江路 1518 弄", header: 1 },
        { date: "2016-05-04", name: "王2", address: "金沙江路 1517 弄", header: 2 }
      ]
    };
  }
};
</script>

代码

<script>
import Vue from "vue";
import Component from "vue-class-component";

@Component({
  props: {
    columns: {
      type: Array,
      default: () => []
    }
  }
})
export default class Table extends Vue {
  get ref() {
    return this.$children[0];
  }

  render(h) {
    const Col = () =>
      this.columns.map(item => {
        const { render, renderHead, ...attrs } = item;
        const prop = { attrs, scopedSlots: {} };
        if (render) {
          prop.scopedSlots.default = function(props) {
            return render(props, h);
          };
        }
        if (renderHead) {
          prop.scopedSlots.header = function(props) {
            return renderHead(props, h);
          };
        }
        return <el-table-column {...prop} />;
      });

    return (
      <el-table
        {...{
          attrs: this.$attrs,
          on: this.$listeners
        }}
      >
        <Col />
        {this.$slots.default}
        <template slot="append">{this.$slots.append}</template>
      </el-table>
    );
  }
}
</script>

简化优化

<script>
export default {
  props: {
    columns: {
      type: Array,
      default: () => []
    }
  },
  computed: {
    ref() {
      return this.$refs.table;
    }
  },
  render() {
    const Col = () =>
      this.columns.map(item => {
        const { component, render, on, ...attrs } = item;
        const prop = { attrs, on, scopedSlots: {} };
        if (render) {
          if (typeof render === "function") {
            prop.scopedSlots.default = props => render(props);
          } else {
            Object.keys(render).forEach(key => {
              prop.scopedSlots[key] = props => render[key](props);
            });
          }
        }
        if (component) {
          return <component is={component} {...prop} />;
        }
        return <el-table-column {...prop} />;
      });
    const Slots = () => {
      const slots = this.$scopedSlots || {};
      return Object.keys(slots).map(slot => {
        if (slot === "default") {
          return slot.default;
        }
        return <template slot={slot}>{slots[slot]}</template>;
      });
    };
    return (
      <el-table ref="table" {...{ attrs: this.$attrs, on: this.$listeners }}>
        <Col />
        <Slots />
      </el-table>
    );
  }
};
</script>

测试

<template>
  <div class="home">
    <el-button @click="clear">取消选中</el-button>
    <el-button @click="toggleSelection([data[1], data[2]])">
      取消第二、三行选中
    </el-button>
    <table-client
      ref="table"
      tooltip-effect="dark"
      style="width: 100%; margin-top: 15px;"
      :data="data"
      :columns="columns"
      :default-sort="{ prop: 'date', order: 'descending' }"
      fit
      lazy
      stripe
      border
      @selection-change="handleSelectionChange"
    >
      <el-table-column label="Date" prop="date" />
      <div slot="append" class="cell" style="padding: 8px 0;">1</div>
    </table-client>

    <div style="text-align: right;margin-top: 12px;">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page.sync="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="100"
        layout="sizes, prev, slot, next"
        :total="1000"
      >
        <template>
          <ul class="el-pager">
            <li class="number">壹</li>
            <li class="number">貳</li>
            <li class="number active">参</li>
            <li class="number">肆</li>
            <li class="number">伍</li>
          </ul>
        </template>
      </el-pagination>
    </div>
  </div>
</template>
<script>
import TableClient from "@/components/Table-client";
export default {
  name: "Home",
  components: { TableClient },
  data() {
    return {
      currentPage: 1,
      multipleSelection: [],
      columns: [
        {
          type: "selection",
          align: "center"
        },
        {
          type: "index",
          label: "序号",
          index: index => index,
          width: "80",
          align: "center"
        },
        {
          prop: "date",
          label: "日期",
          width: "180",
          align: "center",
          sortable: true
        },
        { prop: "name", label: "姓名", width: "180" },
        { prop: "address", label: "地址" },
        {
          prop: "header",
          label: "自定义头部",
          render: ({ column, $index }) => {
            return (
              <div>
                {column.label}-{$index}
              </div>
            );
          }
        },
        {
          prop: "op",
          label: "操作",
          render: {
             default: ({ row }) => (<div>{row.address}</div>),
             header: ({ column, $index }) => <div>{column.label}-{$index}</div>
          }
        }
      ],
      data: [
        {
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
          header: 1
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1517 弄",
          header: 2
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
          header: 3
        },
        {
          date: "2016-05-03",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1516 弄",
          header: 4
        }
      ]
    };
  },
  methods: {
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    toggleSelection(rows) {
      if (rows) {
        rows.forEach(row => {
          this.$refs.table.ref.toggleRowSelection(row);
        });
      } else {
        this.clear();
      }
    },
    clear() {
      this.$refs.table.ref.clearSelection();
    }
  }
};
</script>

效果

 

posted @ 2020-10-14 16:21  .K_o  阅读(183)  评论(0)    收藏  举报