1. 程式人生 > 程式設計 >基於Element封裝一個表格元件tableList的使用方法

基於Element封裝一個表格元件tableList的使用方法

我們專案中使用的表格一般都比較類似,如果不進行封裝的話,那麼每個頁面都可能有一些類似的程式碼。不僅浪費時間,而且由於開發人員不同的開發習慣。後期維護人員需要花費一點時間去看每個人的程式碼。所以我直接將表格做一個二次封裝,只要一個人去維護這份程式碼即可。下面是我封裝的內容

內容:

1、支援直接傳入後臺請求地址渲染列表,且引數修改之後自動重新整理
2、支援自定義每一列的顯示
3、支援根據內容自動撐開列寬
4、支援動態篩選表頭
5、支援分頁
6、防抖
7、列許可權
...
更多請自行嘗試

以下是tableList 元件的程式碼

<template>
<!--重新整理按鈕 和 篩選列的多選框 layout中要有 control 才顯示,預設顯示-->
 <div class="table">
 <div class="table-control" v-if="layoutKey.control">
  <div class="table-control-title" @click="reload">
  <i class="el-icon-refresh"></i></div>
  <el-dropdown class="table-control-title">
  <span class="el-dropdown-link"><i class="el-icon-s-operation table-control-icon"></i></span>
  <el-dropdown-menu slot="dropdown" class="table-control-checkbox">
   <el-checkbox-group v-model="headItems" @change="changeChecked">
   <el-checkbox class="table-control-checkbox-item"
       v-for="(item,index) in allColumn"
       :label="item"
       :key="index">{{item}}
   </el-checkbox>
   </el-checkbox-group>
  </el-dropdown-menu>
  </el-dropdown>
 </div>
 <!--列表主體-->
 <el-table class="table" style="width: 100%"
    ref="tableList"
    :data="tableData"
    :defaultSort.async="defaultSort"
    v-bind="$attrs"
    v-on="$listeners"
    @selectionChange="selectionChange"
    @sort-change="sortChange">
  <ex-table-column v-if="layoutKey.expand" type="expand" fixed>
  <slot name="expand" :data="props" slot-scope="props"/>
  </ex-table-column>
  <ex-table-column v-if="layoutKey.checkBox" fixed type="selection" :width="62"
      :selectable="selectable"/>
  <ex-table-column v-if="layoutKey.index" type="index" label="序號" width="60"/>
  <ex-table-column v-for="(column,index) in activeColumn" :key="index"
      :prop="column.field"
      :column-key="column.field" :label="column.title" :fixed="column.fixed"
      :sortable="column.sort" :selectable="column.selectable"
      :show-overflow-tooltip="column.tooltip"
      :autoFit='true' :width="column.width"
      :fitByClass="autoWidth(column.width)"
      :minWidth="column.minWidth || defaultWidth">
  <slot :name="column.field" :data="scope.row" :field="column.field" :content="column.field"
    :index="index" slot-scope="scope">
   <div>{{$utils.nvl(scope.row[column.field],'--')}}</div>
  </slot>
  </ex-table-column>
 </el-table>
 <!--分頁控制元件,layout中要有 control 才顯示,預設顯示-->
 <el-pagination background small class="table-pagination"
     :current-page.sync="page.pageNo"
     :page-sizes="page.list"
     :page-size="page.pageSize"
     :layout="page.layout" :total="page.total"
     @current-change="handleCurrentChange"
     @size-change="handleSizeChange" v-if="layoutKey.page"/>
 </div>
</template>

<script>
 import debounce from 'lodash/debounce';
 import ExTableColumn from './ExTableColumn';

 export default {
 components: { ExTableColumn },// 提供出來給其他元件呼叫,具體用法參考 vue 官方用法
 provide() {
  return {
  tableList: this,};
 },props: {
 // 預設的表格大小
  defaultWidth: {
  type: Number,required: false,default: 100,},// 顯示的控制元件,目前就page,control 兩個可選,可根據需求自行擴充套件
  layout: {
  default: 'page,control',// 多選時 返回的key,預設id
  checkKey: {
  type: [Number,String],default: () => 'id',// 請求引數,必填
  req: {
  type: Object,required: true,default: () => ({
   url: undefined,type: 'post',params: {
   query: {},pageNo: 1,pageSize: 1,}),// 預設排序,參考 elementUI table 用法
  defaultSort: {
  type: [String,Object],// 列表顯示的列
  // {
   title : 必填 String,  顯示的列名
   field : 必填 String ,  列中的key
   width : 選填,String  列寬,單位畫素,fixed : 選填,String  是否固定的列,可選 right,left
   sort : 選填,Boolean  是否可排序
   expend: 選填,Boolean  是否可展開,配置slot:expand 顯示展開內容
   limit :  選填,Boolean  許可權控制,false 則不顯示
  }
  columns: {
  type: Array,default: () => [{ title: '操作',field: 'ctrl',width: '60',fixed: 'right' }],// 這一行的 CheckBox 是否可以勾選,用法參考elementUI table用法
  selectable: {
  type: Function,default: () => true,// 其他table引數,都會傳給table
 },data() {
  return {
  layoutKey: {},page: {
   list: [5,10,20,50,100],total: null,pageSize: 10,layout: 'total,sizes,prev,pager,next,jumper',tableData: [],sort: '',checkRows: [],checkKeys: [],headItems: [],allColumn: [],activeColumn: [],methods: {
  sortChange({ prop,order }) {
  this.sort = `${prop} ${order === 'descending' ? 'desc' : 'asc'}`;
  this.refresh();
  },selectionChange(selection) {
  this.checkRows = selection;
  this.checkKeys = [];
  selection.map((row) => {
   this.checkKeys.push(row[this.checkKey]);
   return true;
  });
  this.$emit('selectionChange',selection);
  },/** **************************method*********************************** */

  // 分頁
  async handleCurrentChange(currentPage) {
  this.page.pageNo = currentPage;
  this.$emit('handleCurrentChange',currentPage);
  await this.initTable({ vm: this });
  },handleSizeChange(size) {
  this.page.pageSize = size;
  this.page.pageNo = 1;
  this.$emit('handleSizeChange',size);
  this.initTable({ vm: this });
  },/** *****************************動態渲染頭部************************************* */
  // 取消選中選單
  changeChecked() {
  this.changeColumn({ vm: this });
  },changeColumn: debounce(async ({ vm }) => {
  const that = vm;
  const keys = new Set(vm.headItems);
  const activeColumn = vm.columns.filter((item) => {
   if (keys.has(item.title)) {
   return true;
   }
   return false;
  });
  that.activeColumn = activeColumn;
  that.activeColumn.splice(1,0);
  },200),/** *****************************重新整理************************************* */
  // 重新整理表格資料(使用現有引數)
  refresh(type) {
  if (type === 'delete' && this.page.pageNo > 1 && this.tableData.length === 1) {
   this.page.pageNo = this.page.pageNo - 1;
  }
  this.initTable({ vm: this });
  },// 重新載入資料(重置到第一頁)
  reload() {
  if (this.page.pageNo !== 1) {
   this.page.pageNo = 1;
  }
  this.initTable({ vm: this });
  },initTable: debounce(async ({ vm }) => {
  const that = vm;
  that.tableData = [];
  const params = that._.assign({
   pageNo: that.page.pageNo,pageSize: that.page.pageSize,sortStr: that.sort
  },that.req.params); // 右值覆蓋左值,返回左值
  // 發起請求,根據實際專案中,介面來做
  const { data } = await window.axios[that.req.type || 'post'](that.req.url,params);
  if (data && that.$utils.Type.isArray(data.result)) {
   that.tableData = data.result;
   that.page.total = data.total * 1;
  }
  that.$nextTick(() => {
   that.$emit('loadDone',that.tableData,params);
  });
  },300),getCheckRows() {
  return this.checkRows;
  },getCheckKeys() {
  return this.checkKeys;
  },handleHead(columns) {
  const allColumn = [];
  columns.map((item) => {
   if (!item.limit) {
   allColumn.push(item.title);
   }
   return true;
  });
  this.headItems = allColumn;
  this.allColumn = allColumn;
  this.changeChecked();
  },handleLayout() {
  const layout = this.layout;
  if (!layout) return null;
  layout.split(',')
  .map(
   (item) => {
   const key = item.trim();
   this.layoutKey[key] = true;
   return true;
   },);
  return this.layoutKey;
  },autoWidth(width) {
  if (this.$utils.isEmpty(width)) {
   return 'cell';
  }
  return width;
  },init() {
  this.handleLayout();
  this.handleHead(this.columns);
  if (this.defaultSort) {
   const { prop,order } = this.defaultSort;
   this.sort = `${prop} ${order === 'descending' ? 'desc' : 'asc'}`;
  }
  this.initTable({ vm: this });
  },async created() {
  this.init();
 },watch: {
  queryParams: {
  handler() {
   this.reload({ vm: this });
  },columns: {
  handler() {
   this.handleHead(this.columns);
  },computed: {
  queryParams() {
  if (this.$utils.isNotEmpty(this.req.params)) {
   return this.req.params;
  }
  return {};
  },};
</script>

<style lang="less" scoped>
 @import './style/index';
</style>

使用方法

<template>
 <div>
 <table-list
  :req="tableReq"
  ref="tableList"
  :stripe="true" // table 原來的引數也是支援使用的,方法也支援使用。
  :columns="[
     {title:'使用者名稱',field:'name',sort:'true',fixed:true},{title:'英文名',field:'aliasName',{title:'年齡',field:'age',sort:true},{title:'職業',field:'job',{title:'郵箱',field:'email'},{title:'出生日期',field:'birthday'},{title:'家庭住址',field:'address'},{title:'戶籍',field:'domicile'},]">
  <!--格式化時間列,所有的列都可以這麼使用,slot 名為列field-->
  <template slot="birthday" slot-scope="{data}">
  <span>{{format(data.birthday)}}</span>
  </template>
 </table-list>
 </div>
</template>

<script>
 import TableList from './table/components/TableList';

 export default {
 name: 'HelloWorld',components: { TableList },data() {
  return {
  tableReq: {
   url: '/user/list',//必填
   type: 'post',//可選,預設 post
   params: {} // 可選
  }
  };
 },methods: {
  format(time) {
  if (this.$utils.isEmpty(time)) return '/';
  return this.$utils.format(new Date(time),'yyyy-MM-dd HH:mm');
  },mounted() {
 }
 };
</script>

以下是顯示效果

基於Element封裝一個表格元件tableList的使用方法

到此這篇關於基於Element封裝一個表格元件tableList的使用方法的文章就介紹到這了,更多相關Element tableList內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!