基于Element的表格组件封装

188 阅读2分钟

需求

常规的后台管理系统会经常用到表格展示数据,而element自带的表格需要花很多代码编写HTML部分,为了减少编写的代码以及增加表格的可配置性,减少需求变更时代码的编写量,所以需要对表格进行二次封装。需求入下:

  1. 通过JS的方式配置表格的列数据,继承原本列的可配置项
  2. 存在一定的可扩展性,能够自定义列数据

代码

<!--表格组件-->
<template>
  <div class="makeid-table">
    <el-table 
      element-loading-text="数据加载中" 
      v-loading="loading" 
      :data="dataList" 
      height="100%"
      border
      @selection-change="selectionChange"
      v-adaptive="{type:'table',bottomOffset:bottomOffset}"
      :key="tableKey"
      :row-key="getRowKeys"
    >
      <el-table-column :reserve-selection="true" align="center" v-if="isSelection" type="selection" width="55" />
      <el-table-column align="center" type="index" label="序号" width="50px" />
      <el-table-column align="center" v-for="item in columns" :key="item.prop" v-bind="item">
        <!-- 根据实际情况传入自定义内容 -->
        <template v-slot="{ row, $index }">
          <slot :name="item.prop" :row="row" :index="$index">
            {{ row[item.prop] }}
          </slot>
        </template>
      </el-table-column>
    </el-table>
    <!-- 底部部分 -->
    <div class="footer" v-if="isPagination">
      <el-pagination 
        background 
        layout="total, prev, pager, next, sizes,jumper" 
        :total="pagination.total"
        :page-size="pagination.pageSize" 
        :page-sizes="pagination.pageRange" 
        :current-page="pagination.pageNo"
        @current-change="currentChange" 
        @size-change="sizeChange">
      </el-pagination>
    </div>
  </div>
</template>
<script>
  export default {
    props: {
      tableKey: {
        type: String,
        default: ''
      },
      loading:{
        type:Boolean,
        default:true
      },
      dataList:{
        type:Array,
        default(){
          return []
        }
      },
      columns:{
        type:Array,
        default(){
          return []
        }
      },
      isSelection: {
        type: Boolean,
        default: false,
      },
      isPagination: {
        type: Boolean,
        default: true
      },
      pagination: {
        type: Object,
        default () {
          return {
            pageNo: 1,
            pageSize: 10,
            total: 0,
            pageRange: [10, 20, 30, 50, 100],
          }
        }
      },
      currentChange:{
        type:Function,
        default:()=>{}
      },
      sizeChange:{
        type:Function,
        default:()=>{}
      },
      selectionChange:{
        type:Function,
         default:()=>{}
      },
      bottomOffset:{
        type:String,
        default:'60'
      },
      rowId:{
        type:String,
        default:'id'
      }
    },
    data() { return {} },
    mounted() { },
    methods: {
      // 跨页多选
      getRowKeys(row) {
        return row[this.rowId]
      },
    }
  }
</script>
<style lang='scss' scoped>
.makeid-table{
  .footer{
    margin-top:10px;
  }
}

讲解

实现思路

动态列实现的就是通过for循环去生成列数据,在循环生成列时,通过v-bind="item" 可以很方便的绑定外界传进来的属性用在element-column上,不需要使用prop的方式,再利用命名插槽的作用能够让用户自定义列的数据,getRowKeys的作用是实现跨页多选,具体可百度查询。

一些问题

该组件传递了很多Function,比如currentChange,sizeChange等,这是可以优化的,因为在项目中统一封装了tableMixins.js封装了这几个函数所以就统一传进来了,如果需要优化可以使用model:update的方式实pagination双向绑定就可以减少这几个函数的传入,具体实现可自行编写。因为现在项目主要是vue3,所以后续再封装vue3版本的表格组件。
v-adaptive="{type:'table',bottomOffset:bottomOffset}" 是一个自定义指令用于自适应表格高度撑满容器,不需要可自行删除,如果需要,评论区留言,后续补上。

使用

<MakeidTableBox
  tableKey="DealOrder_List"
  bottomOffset="85"
  :loading="loading"
  :dataList="dataList"
  :columns="columns"
  :pagination="pagination"
  :currentChange="handleCurrentChange"
  :sizeChange="handleSizeChange"
>
  //operation 是操作列
  <template #operation="{ row }">
    <el-button
      @click="handleDownload(row)"
      class="table-icon"
      type="text"
      size="medium"
    >
      <i class="el-icon-download"></i>
      <span>下载</span>
    </el-button>
    <el-button
      class="table-icon"
      @click="handleDelete(row)"
      type="text"
      size="medium"
    >
      <i class="el-icon-delete"></i>
      <span>删除</span>
    </el-button>
  </template>
</MakeidTableBox>
// JS 部分 变量定义
loading:false,
dataList:[],
columns: [
    { label: "单据编号",prop: "invoiceCode"},
    { label: "文件名称",prop: "fileName"},
    { label: "报废单位",prop: "assetUnit"},
    { label: "备注",prop: "remark"},
    { label: "创建人", prop: "createUser", width: "160"},
    { label: "创建时间",prop: "createDate",width: "160"},
    { label: "操作",prop: "operation",width: "160"},
  ],
pagination: {
pageNo: 1,
pageSize: 10,
total: 0,
pageRange: [10, 20, 30, 50, 100],
},

总结

目前组件实现的还比较粗糙,不过能够覆盖业务中大部分表格使用,后续有其他需求时再优化,如果有更好的意见欢迎评论,学习一下。