封装elementUI的表格分页组件

首先我们新建一个render.js文件

// render.js
export default {
  functional: true,
  name: 'myRender',
  props: {
    row: Object,
    render: Function,
    index: Number,
    column: {
      type: Object,
      default: null
    }
  },
  render: (h, content)=>{
    const {props} = content;
    const params = {
      row: props.row,
      index: props.index
    }
    return props.render(h, params);
  }
}

然后我们再新建一个myTable.vue文件

// myTable.vue
<template>
  <div>
    <el-table :row-key="rowKey"  @sort-change="sortChange" @header-click="headerClick"
       :data="tableData"  @selection-change="handleSelectionChange" :show-summary="showSummary" 
       :sum-text="sumText"  :summary-method="getSummaries" ref="multipleTable"
       highlight-current-row style="width: 100%;" v-loading="loading" element-loading-text="拼命加载中"   
       element-loading-spinner="el-icon-loading" header-row-class-name="myTableHeadClass" class="myTableClass">
      <slot name="columnHead"></slot>
      <el-table-column v-bind="item"  v-for="(item,i) in tableColumnList" :key="`${item}${i}`" :sortable="item.sortable || false">
        <template  slot="header" slot-scope="{row}" >
            <myRender  v-if="item.headerRender" :render="item.headerRender" :row="row"  :column="item" ></myRender>
           
         <span v-else>
          {{item.label}}
        </span>
        </template>
        <template slot-scope="{row}" v-if="!item.type">
            <myRender v-if="item.render" :render="item.render" :row="row"  :column="item" ></myRender>
            <div v-else>{{ item.isFormatTime ? timeFormat(row[item.prop]) : row[item.prop]}}</div>

        </template>
      </el-table-column>
      <slot name="columnFoot"></slot>
    </el-table>

    <myPagination v-show="needPagination" :count="count" :initData="initData" ref="myPagination"></myPagination>

    <my-dialog title="表头筛选" :dialoShow="dialoShow"  @updateSave="updateSave" @closeDialo="dialoShow=false;" :width="40" >
      <div class='checkBox'>
        <el-checkbox-group v-model="checkList" >
          <el-checkbox  :label="item.label" class="checkOne"  v-for="item in columnList" :key="item.id"></el-checkbox>
        </el-checkbox-group>
      </div>
    </my-dialog>

  </div>
</template>

<script>
import dateUtil from 'fecha'; //处理时间格式的一个插件
import myPagination from './myPagination.vue';
import myRender from './render.js';
import myDialog from './dialog.vue';

export default {
  props:{
    columnList:{   // 表格列的数据
      type:Array,
      default:[]
    },
    dataParams:{
      type:Object,
      required: false
    },
    url:String,
    fetchMethods:{
      type: String,
      required: false,
      default: 'get',
    },

    showSummary:{   // 设置为true就会在表格尾部展示合计行
      type: Boolean,
      required: false,
      default: false,
    },
    sumText:{      // 总计显示名字
      type: String,
      required: false,
      default: '总计',
    },
    computedFunc:{  // 自定义总计的计算方法
      type: Function,
      required:false
    },
    getSummaries:  {
      type: Function,
      required: false,
      default: function (param){
        if(this.computedFunc)return this.computedFunc(param);
        const { columns, data } = param;
        const sums = [];
        columns.forEach((column, index) => {
          if (index === 0) {
            sums[index] = this.sumText;
            return;
          }

          const values = data.map(item => {
            let num = item[column.property];

            if(typeof item[column.property] === 'string' && item[column.property].includes('%')){
              num = num.replace(/%$/g,'');
              column.hasPercentSign = true; // 该列是否含有百分号
            }

            return  Number(num);

          });
          if (!values.every(value => isNaN(value))) {
            sums[index] = values.reduce((prev, curr) => {
              const value = Number(curr);
              if (!isNaN(value)) {
                return prev + curr;
              } else {
                return prev;
              }
            }, 0);
            if(column.property === 'passRateStr'){ // 通过率=通过好友数/打招呼数
              const passNumIndex = columns.findIndex(v=>v.property === 'passNum');
              const greetingNumIndex = columns.findIndex(v=>v.property === 'greetingNum');
              if(passNumIndex > -1 && greetingNumIndex > -1){
                sums[index] = sums[greetingNumIndex] === 0 ? 0 :  sums[passNumIndex] / sums[greetingNumIndex] * 100;
              } else {
                sums[index] = '/';
                column.hasPercentSign = false;
              }
            } else if(column.property === 'replyRateStr'){ //  回复率=会员回复数/通过好友数
              const passNumIndex = columns.findIndex(v=>v.property === 'replyNum');
              const greetingNumIndex = columns.findIndex(v=>v.property === 'passNum');
              if(passNumIndex > -1 && greetingNumIndex > -1){
                sums[index] = sums[greetingNumIndex] === 0 ? 0 : sums[passNumIndex] / sums[greetingNumIndex] * 100;
              } else{
                 sums[index] = '/';
                 column.hasPercentSign = false;
              }
            } else if(column.property === 'passAllocateRateStr'){ //  分配率=分配数/通过好友数
              const passNumIndex = columns.findIndex(v=>v.property === 'allocateNum');
              const greetingNumIndex = columns.findIndex(v=>v.property === 'passNum');

              if(passNumIndex > -1 && greetingNumIndex > -1){
                sums[index] = sums[greetingNumIndex] === 0 ? 0 : sums[passNumIndex] / sums[greetingNumIndex] * 100;
              } else{
                 sums[index] = '/';
                 column.hasPercentSign = false;
              }
            } else if(column.property === 'allocateRateStr'){ //  资源分配率=分配数/添加数
              const passNumIndex = columns.findIndex(v=>v.property === 'allocateNum');
              const greetingNumIndex = columns.findIndex(v=>v.property === 'addNum');

              if(passNumIndex > -1 && greetingNumIndex > -1){
                sums[index] = sums[greetingNumIndex] === 0 ? 0 :  sums[passNumIndex] / sums[greetingNumIndex] * 100;
              } else{
                 sums[index] = '/';
                 column.hasPercentSign = false;
              }
            } else if(column.property === 'deleteRateStr'){ //   删除率=删除数/通过好友数
              const passNumIndex = columns.findIndex(v=>v.property === 'deleteNum');
              const greetingNumIndex = columns.findIndex(v=>v.property === 'passNum');

              if(passNumIndex > -1 && greetingNumIndex > -1){
                sums[index] = sums[greetingNumIndex] === 0 ? 0 :  sums[passNumIndex] / sums[greetingNumIndex] * 100;
              } else{
                 sums[index] = '/';
                 column.hasPercentSign = false;
              }
            }
            if(column.hasPercentSign){
              sums[index] = sums[index].toFixed(2);
              sums[index]+= '%';
            }
          } else {
            sums[index] = '/';
          }
        });

        return sums;
      }
    },
    needPagination:{  // 是否需要分页
      type: Boolean,
      required: false,
      default: true,
    },
    columDefaultShow:{
      type:Array,
      default:()=>{
        return [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
      }
    },
    rowKey:{
      type: Function,
      default:(row)=>{
        let checkRepeatObj = {}
        if (row) {
          if (row.id) {
            if (checkRepeatObj[row.id]) {
              if (!row._secondId) {
                row._secondId = Math.random() + ''
              }
              /** 方便根据key重用元素 */
              return row._secondId
            } else {
              checkRepeatObj[row.id] = 1
              return row.id
            }
          }
          // row.id不存在
          if (!row._secondId) {
            row._secondId = Math.random() + ''
          }
          return row._secondId
        } else {
          //  row为空
          return Math.random() + ''
        }
      }
    }
  },
  data(){
    return{
      checkRepeatObj: {},
      tableData:[],
      loading: false,
      count: 0,
      initParams:{},
      dialoShow: false,
      checkList: [],
      tableColumnList: [],
      multipleSelection: [],
    }
  },
  created(){
    for(const val of this.columDefaultShow) {
     if(this.columnList[val])this.tableColumnList.push(this.columnList[val]);
    }
  },
  methods:{
    timeFormat(time, type="YYYY-MM-DD HH:mm:ss"){
      return  time ? dateUtil.format(new Date(time), type) : '';
    },
    clearSelection(){
      this.$refs.multipleTable.clearSelection();
    },
   
    handleSelectionChange(val){
      this.$emit('handleSelectionChange',val);
    },
    async initData(obj={}){
      this.initParams = Object.assign(this.initParams,obj);
      const data = Object.assign({
        pageSize: this.$refs.myPagination.getPageSize(),
        pageNo: this.$refs.myPagination.getPageNo() - 1,
      }, this.dataParams,this.initParams);
      const methods = this.fetchMethods.toLowerCase();
      this.loading = true;
      if(methods === 'get' ){
        await this.$get(this.url, data, {timeout:60000}).then((res) => {
          this.loading = false;
          this.tableData = Object.assign([], res.list ? res.list : res.data ? res.data : []);
          this.count = res.count ? res.count : 0;
          this.$emit('getTableData',this.tableData, this.count);
        }).catch((err) => {
          this.loading = false;
          this.tableData = [];
          this.count = 0;
          this.$emit('getTableData',this.tableData, this.count);

        });
      } else {
        await this.$post(this.url, data, {timeout:60000}).then((res) => {
          this.loading = false;
          this.tableData = Object.assign([], res.list ? res.list : res.data ? res.data : []) 
          this.count = res.count ? res.count : 0;
          this.$emit('getTableData',this.tableData, this.count);
        }).catch((err) => {
          this.loading = false;
          this.tableData = [];
          this.count = 0;
          this.$emit('getTableData',this.tableData, this.count);

        });

      }



    },
    setTableData(data=[]){
      if(this.$refs.myPagination)this.$refs.myPagination.setPageNo();
      if(this.$refs.myPagination)this.$refs.myPagination.setPageSize();
      this.loading = false;
      this.tableData = Object.assign([],data);
      this.count = this.tableData.length;
    },
    async search(obj={}, resetPageSize=true){
      if(this.$refs.myPagination)this.$refs.myPagination.setPageNo();
      if(this.$refs.myPagination&&resetPageSize)this.$refs.myPagination.setPageSize();
      await this.initData(obj);
    },
    sortChange(row){
      this.$emit('sortChange', row);
    },
    getPageSize(){
      return this.$refs.myPagination.getPageSize();
    },
    getPageNo(){
      return this.$refs.myPagination.getPageNo();
    },
    headerClick(column, event){
      if(column.type === "selection")return;
      this.dialoShow = true;
      this.checkList = this.tableColumnList.map(v=>v.label);
    },
    updateSave(){
      this.tableColumnList = this.columnList.filter(v=>this.checkList.includes(v.label));
      this.dialoShow = false;

    },

  },
  components:{myRender,myPagination,myDialog}

}
</script>

<style scoped>
.checkBox .checkOne{
  width: 20%;
  margin-bottom: 16px;
}
.headImg, .headImg img{
  width: 36px;
  flex-shrink: 0;
  flex-basis: 36px;
  height: 36px;
}

</style>

Tips:文中myPagination组件和myDialog组件都是我自己分装的分页和弹窗组件,可查看我的上两篇文章找到相应代码,也可以直接点击链接跳转过去myPaginationmyDialog

使用方式:

// xxx.vue中
<template>
<el-form   :inline="true" class="demo-form-inline" @submit.native.prevent>
          <el-form-item label="邮箱" >
            <el-input placeholder="请输入邮箱" v-model.trim="email" clearable @keydown.enter.native="search"></el-input>
          </el-form-item>
           <el-form-item label="状态" >
             <el-select filterable clearable v-model="status" placeholder="请选择状态" @change="search">
                    <el-option
                        v-for="item in statusList"
                        :key="item.id"
                        :label="item.name"
                        :value="item.id">
                    </el-option>
                </el-select>
          </el-form-item>

            <el-button type="primary" @click.stop="search" size="small" class="blueBgBtn ">查询</el-button>
            <el-button type="primary" @click.stop="addGateway" size="small" class="grayBgBtn">新增</el-button>
          
        </el-form>
  <myTable ref="myTable" :columnList="columnList" :dataParams="dataParams"  url="/workapi/chatgptToken/queryList"   >
        
           <template v-slot:columnFoot>
              <el-table-column label="操作" width="120">
                <template slot-scope="scope">
                  <i class="el-icon-edit iconBlueBtn iconMarRight" title="编辑"    @click.stop="handleEdit(scope.row)"></i>
                </template>
              </el-table-column>
          </template>
        </myTable>
</template>

<script>

import myTable from "@/components/myTable.vue";
export default{
  data(){
   this.columnList = [
       {label: '邮箱', prop:'email'},
       {label: 'token', prop:'token'},
      
      {label: '状态', prop:'status', render: (h,{row}) => {
        const statusObj = this.statusList.find(v=>v.id === row.status);
        return h('div', {
          class: {
            redText: row.status === 0,
            blueText: row.status === 1,
          }
        }, statusObj ? statusObj.name : '')
      }},
      {label: '备注', prop:'remark',render:(h,params)=>{
         if(!params.row.remark || params.row.remark.length < 20){
            return h('div', params.row.remark);
          } else {
            return h("el-popover",{
              attrs:{
               placement: 'top-start',
               width: '300',
               trigger: 'hover',
               content: params.row.remark
             }
            },[h('div', {
              slot: 'reference',
              class:{
                nowrapEllipsis: true,
                poiner: true
              },
           }, params.row.remark)])
          }
       }},
      {label: '创建人', prop:'creatorName'},
       {label:'创建时间', prop: 'createTime', isFormatTime:true,width:160},

     ]
  },
   computed:{
    dataParams(){
      return {
        email:this.email,
        status:this.status,
      }
    }
  },
  methods:{
	  initData(){
	      this.$refs.myTable.initData(this.dataParams);
	    },
	    search(){
	      this.$refs.myTable.search(this.dataParams);
	    },
	    handleEdit(row){
	    		console.log(row)
		}
	},
	 components:{ myTable}
 }
</script>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值