基于element-ui框架封装el-table组件

3,621 阅读4分钟

<template>
  <el-table
    :data="tableData"
    border
    style="width: 100%">
    <el-table-column
      fixed
      prop="date"
      label="日期"
      width="150">
    </el-table-column>
    <el-table-column
      prop="name"
      label="姓名"
      width="120">
    </el-table-column>
    <el-table-column
      prop="province"
      label="省份"
      width="120">
    </el-table-column>
    <el-table-column
      prop="city"
      label="市区"
      width="120">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址"
      width="300">
    </el-table-column>
    <el-table-column
      prop="zip"
      label="邮编"
      width="120">
    </el-table-column>
    <el-table-column
      fixed="right"
      label="操作"
      width="100">
      <template slot-scope="scope">
        <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
        <el-button type="text" size="small">编辑</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
  export default {
    methods: {
      handleClick(row) {
        console.log(row);
      }
    },

    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1518 弄',
          zip: 200333
        }, {
          date: '2016-05-04',
          name: '王小虎',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1517 弄',
          zip: 200333
        }, {
          date: '2016-05-01',
          name: '王小虎',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1519 弄',
          zip: 200333
        }, {
          date: '2016-05-03',
          name: '王小虎',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1516 弄',
          zip: 200333
        }]
      }
    }
  }
</script>
代码有点多,维护起来有点痛苦。特别是当字段超过50个以后!!!

为什么要对进行二次封装?

1 element-ui组件的部分样式不满足当前项目的需求

2 产品要求排序方式只有asc,desc两个,不可取消排序。

3 提高代码复用性


<template>
     <ftoTable      
      stripe   
     border   
     @cell-click="handleitemChange"  
     :ajaxConfig="ajaxConfig"     
     :Action="Action"  
    height="250"    
     @sort-change="sorthandle"    
    :default-sort="sortMap"   
     :columns="tableHeadData"    >    
            <template v-slot:first>      
               <el-table-column label="序号" type="index" width="50"></el-table-column>     
           </template>   
 </ftoTable>
</template>

<script>
import { getList } from "@/api/table";
import moment from "moment";
export default {  filters: {  
  statusFilter(status) {   
   const statusMap = {     
   published: "success",       
   draft: "gray",    
    deleted: "danger"    
  };      
return statusMap[status];    }  },
  data() {   
      return {      

   list: null,    
   listLoading: true,    
   activeName: "first",   
   queryparam: {       
   selectDateInfo: {},    
    Areacode: ""   
   },      
   tableHeadData: [     {          prop: "author",    
                                   label: "作者",        
                                   className: "allowclick",      
                                   allowclick: true //允许下钻      
                         }, 
                        {           prop: "display_time",        
                                    label: "时间",         
                                    sortable: "custom",        
                                    className: "allowclick",        
                                    allowclick: true       
                         },   
                        {          prop: "status",          
                                   label: "状态",       
                                   sortable: "custom"      
                        }      
               ],    
    sortMap: {      
         prop: "display_time",//排序字段名称     
         order: "descending" //倒叙    
      },  
    ajaxConfig: {    
      requestapi: getList,     
       dataKey: "items"     
     },    
  Action: "" //Action=>query 执行查询    };  },  created() {}, 
 methods: {   
 fetchData() {     
      this.listLoading = true;   
      getList().then(response => {       
            this.list = response.data.items;     
           this.listLoading = false;    
     });   
 },   
 handleitemChange(row, column, cell, event) {   
      let { property } = column;    
      let Headitem = this.tableHeadData.find(item => item.prop == property);      //处理下钻 
      if (Headitem.allowclick == true) {       
        console.log("allowclick", "aaaaaaaaa");     
      }   
  },  
  sorthandle() {      
    console.log("aaaaaaaa"); 
   },   
   handleClick(tab, event) {      
     console.log(tab, event);  
   },  
   queryHandle() {     
       this.Action = "query";    
       setTimeout(()=>{          
         this.Action = "";    
        },500);  
   }  
  }
};
</script>

#columns 表头 必填项
#ajaxConfig 选填
#Action: "" // Action=>query 执行查询 选填
#除了这3个参数,其他用法与el-table api完成一致,妈妈再也不用担心element-ui 属性和方法更新了!

这是怎样实现的呢?


<template> 
 <div class="fto-table-container" v-loading="showLoading">  
  <el-table     
 ref="ftotableDatatable"    
  :data="tableData"   
   v-bind="$attrs"      
v-on="$listeners"    >   
   <slot name="first" />     
 <el-column v-for="(item, index) in columns" :key="index" :item="item" />   
   <slot />  
  </el-table> 
 </div>
</template>
<script>
import ElColumn from "./el-column";
var lang = require("lodash/lang");
import { assign } from "lodash/object";
export default {  
 name: "ftotableDatatable",  
 components: {    ElColumn  },
   props: {   
      serverParams: {      // 查询参数      type: Object    },  
      columns: {      // 指定表格属性      type: Array,      default: () => []    }, 
     pageParams: {      type: Object,      default: () => {}    },    
     ajaxConfig: {      type: Object,      default: () => {}    },     
     Action: {      type: String,      default: () => ""    } 
   },
}...省略

ElColumn组件做了什么操作呢?

<template>
  <el-table-column :type="item.type"          
          :index="item.index"        
           :column-key="item.columnKey"       
            :label="item.label"                 
            :prop="item.prop"                   
            :width="item.width"                
            :min-width="item.minWidth"                 
            :fixed="item.fixed"                   
            :render-header="item.renderHeader"                  
            :sortable="item.sortable || false"                   
             :sort-method="item.sortMethod"     
              :sort-by="item.sortBy"            
             :sort-orders="['ascending', 'descending']"             
              :resizable="item.resizable || true"               
              :formatter="item.formatter"                  
              :show-overflow-tooltip="item.showOverflowTooltip || false"                
              :align="item.align || 'left'"     
              :header-align="item.headerAlign"         
               :class-name="item.className"              
               :label-class-name="item.labelClassName"        
                :selectable="selectable || item.selectable"                
                :reserve-selection="item.reserveSelection || false"          
                :filters="item.filters"                   
                :filter-placement="item.filterPlacement"                   
                :filter-multiple="item.filterMultiple || true"             
                :filter-method="item.filterMethod"                  
                :filtered-value="item.filteredValue">    
                <el-column v-for="(child, index) in item.children"            
   :key="index"               :item="child" />  
   </el-table-column>
</template>
<script>
export default {  
   name: "ElColumn",  
    props: {   
    item: {   
      type: Object,      default: () => null   
   },    
    selectable: {      type: Function    } 
 }
};
</script>


核心代码只有两行,v-bind="$attrs" v-on="$listeners"
$attrs    包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。
当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class和 style 除外),
并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
$listener    包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。
它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。


ftotable完成代码在https://github.com/diliantian/vueftotable.git element-ui框架是非常优秀的vue框架,ftotable采用非侵入式封装,element-ui升级之后仍然可用