美文网首页
如何二次封装el-table

如何二次封装el-table

作者: 小小鱼yyds | 来源:发表于2021-02-20 16:25 被阅读0次

项目中使用了Element UI的表格组件el-table,按照官方提供的写法,展示的列越多,代码量也就越大。如果是开发后台管理系统,需要用到统计的地方有很多。不把时间花在重复的工作上,封装el-table,作为组件引用,只需要少量的配置,就能极大的提高开发效率。
el-table需要面对的场景多种多样,业务不同,呈现出的样式也不同,根据使用的难易程度,把它分为:

  • 1、显示数据从父视图传递,集成只需要一行代码的简易表格——<simpleTable>
  • 2、集成需要配置请求接口、查询参数,有分页,组件内请求数据的表格—— <myTable>

一、simpleTable

<template>
  <div ref="table" >
    <el-table :show-summary="isShowSummary" v-if="!fixHeight" :header-cell-style="{background:headerBgColor}" :data="tableData" ref="multipleTable" border style="width: 100%;" @selection-change="handleSelectionChange">
      <el-table-column v-if="isShowSelection" type="selection" width="55" align="center"></el-table-column>
      <el-table-column type="index" align="center" label="序号" min-width="50" v-if="isShowSerialNumber"></el-table-column>
      <template v-for="k in props">
        <el-table-column v-if="k.fixw" :min-width="k.fixw" align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
        <el-table-column v-else align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
      </template>
      <el-table-column align="center" :fixed="fixedType?'right':fixedType" label="操作" v-if="isShowOperation">
        <slot name="operation" :data="scope.row" slot-scope="scope"></slot>
      </el-table-column>
    </el-table>

    <el-table v-else :height="tableH" :show-summary="isShowSummary" :header-cell-style="{background:headerBgColor}" :data="tableData" ref="multipleTable" border style="width: 100%;" @selection-change="handleSelectionChange">
      <el-table-column v-if="isShowSelection" type="selection" width="55" align="center"></el-table-column>
      <el-table-column type="index" align="center" label="序号" min-width="50" v-if="isShowSerialNumber"></el-table-column>
      <template v-for="k in props">
        <el-table-column v-if="k.fixw" :min-width="k.fixw" align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
        <el-table-column v-else align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
      </template>
      <el-table-column align="center" :fixed="fixedType?'right':fixedType" label="操作" v-if="isShowOperation">
        <slot name="operation" :data="scope.row" slot-scope="scope"></slot>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
  export default {
    props: {
      headerBgColor: {
        type: String,
        default: 'white'
      },
      fixHeight:{   
        type: Boolean,
        default: false
      },
      tableH:{      
        type: Number,
        default: 0
      },
      isShowSelection: {
        type: Boolean,
        default: false
      },
      isShowSerialNumber: {
        type: Boolean,
        default: true
      },
      isShowOperation: {
        type: Boolean,
        default: true
      },
      isShowSummary: {
        type: Boolean,
        default: false
      },
      fixedType:{  
        type: Boolean,
        default: false
      },
      sort: {
        type: Array,
        default: () => []
      },
      props: Array,
      tableData: {
        type: Array,
        default: () => []
      },
    },
    data () {
      return {
      }
    },
    created () {},
    mounted(){},
    methods: {
      handleSelectionChange (val) {
        this.$emit('selectionChange', val)
      }
    }
  }
</script>

SimpleTable

参数 说明 类型 默认值
headerBgColor 表头背景色 String white
fixHeight 是否固定表格高度 boolean false
tableH 表格高度(fixHeight为true, 则tableH必须设定) number 0
isShowSelection 是否开启选择功能 boolean false
isShowSerialNumber 是否显示序号 boolean true
isShowOperation 是否显示操作列 boolean true
isShowSummary 是否显示总计 boolean true
fixedType 是否固定右侧操作栏 boolean false
props 列标题以及对应的参数名数组 Array []
tableData 后台返回的数据 Array []

Table Events

事件名 说明 参数
selectionChange 当选择项发生变化时会触发该事件 row

使用方式:

<template>
   <div class="h-table">
        <simpleTable
         :tableData="chartData2.rows"
         :props="callProps">
          <template #operation="{ data }">
             <a href="javascript:;">查看详情</a>
          </template>
        </simpleTable> 
  </div>
</template>
<script>
import simpleTable from "./../components/simpleTable";
export default {
  name: "home",
  components: {
      simpleTable
  },
  data() {
    return {
         callProps: [
        {
          prop: "date",
          label: "日期",
          fixw: "150"    // 自定义某列宽度
        }, 
        {
          prop: "callNum",
          label: "外呼数",
          sort: true    // 是否可以筛选
        },
        {
          prop: "callSuccess",
          label: "外呼成功数",
        },
        {
          prop: "connectNum",
          label: "接通率",
        },
        {
          prop: "connectDuring",
          label: "外呼平均通话时长",
        },
      ],
      chartData2: {
        rows: [
          { date: "2020-03-04", callNum: 1393, callSuccess: 1093 },
          { date: "2020-03-05", callNum: 3530, callSuccess: 3230 },
          { date: "2020-03-06", callNum: 2923, callSuccess: 2623 },
          { date: "2020-03-07", callNum: 1723, callSuccess: 1423 },
          { date: "2020-03-08", callNum: 3792, callSuccess: 3492 },
          { date: "2020-03-09", callNum: 4593, callSuccess: 4293 },
        ],
      },
    };
  }
};
</script>
<style lang="scss" scoped>
 .h-table{
     width: 90%;
     margin-top: 20px;
     margin-left: 20px;
  }
</style>

二、myTable

<template>
  <div ref="table" v-loading="loading" >
    <el-table v-if="!fixHeigth" :data="tableData" :header-cell-style="{background:headerBgColor}" ref="multipleTable" border style="width: 100%;" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
      <el-table-column v-if="isShowSelection" type="selection" width="55" align="center" :selectable="isSelectable"></el-table-column>
      <el-table-column align="center" label="序号" min-width="70" v-if="isShowSerialNumber">
        <template slot-scope="scope">
          <span>{{scope.$index+(currentPage-1)*pageSize+1}}</span>
        </template>
      </el-table-column>
      <template v-for="k in props">
        <el-table-column v-if="k.fixw" :min-width="k.fixw" align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
        <el-table-column v-else align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
      </template>
      <el-table-column align="center" :fixed="fixedType?'right':fixedType" label="操作" v-if="isShowOperation">
        <slot name="operation" :data="scope.row" slot-scope="scope"></slot>
      </el-table-column>
    </el-table>

    <el-table v-else :height="tableH" :data="tableData" :header-cell-style="{background:headerBgColor}" ref="multipleTable" border style="width: 100%;" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
      <el-table-column v-if="isShowSelection" type="selection" width="55" align="center" :selectable="isSelectable"></el-table-column>
      <el-table-column align="center" label="序号" min-width="70" v-if="isShowSerialNumber">
        <template slot-scope="scope">
          <span>{{scope.$index+(currentPage-1)*pageSize+1}}</span>
        </template>
      </el-table-column>
      <template v-for="k in props">
        <el-table-column v-if="k.fixw" :min-width="k.fixw" align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
        <el-table-column v-else align="center" :prop="k.prop" :label="k.label" :sortable="k.sort ? true : false">
          <slot :name="k.prop" :data="scope.row" slot-scope="scope">{{scope.row[k.prop]}}</slot>
        </el-table-column>
      </template>
      <el-table-column align="center" :fixed="fixedType?'right':fixedType" label="操作" v-if="isShowOperation">
        <slot name="operation" :data="scope.row" slot-scope="scope"></slot>
      </el-table-column>
    </el-table>

    <div class="bottom-row" v-if="isShowPagination">
      <el-pagination
        @current-change="handleCurrentChange"
        :page-size="pageSize"
        :current-page.sync="currentPage"
        layout="prev, pager, next, jumper, total"
        :total="total">
      </el-pagination>
    </div>
  </div>
</template>
<script>
  export default {
    props: {
      headerBgColor: {
        type: String,
        default: 'white'
      },
      isShowSelection: {
        type: Boolean,
        default: false
      },
      immediate: {
        type: Boolean,
        default: true
      },
      fixHeigth:{   //固定高度
        type: Boolean,
        default: false
      },
      isShowSerialNumber: {
        type: Boolean,
        default: true
      },
      isShowOperation: {
        type: Boolean,
        default: true
      },
      isShowPagination: {
        type: Boolean,
        default: true
      },
      isSecondLayer: {
        type: Boolean,
        default: true
      },
      isPost: {
        type: Boolean,
        default: true
      },
      isCustomTime:{  // 起始时间划分为两个参数的情况
        type: Boolean,
        default: false
      },
      tableH:{        // 表格高度,横向内容超过可视区域时适配小屏幕电脑
        type: Number,
        default: 0
      },
      fixedType:{  // 是否固定右侧操作栏
        type: Boolean,
        default: false
      },
      isArray: {
        type: Boolean,
        default: true
      },
      callback: Function,
      sort: {
        type: Array,
        default: () => []
      },
      query: Object,
      props: Array,
      action: String,
      isSelectable: Function,
      dataList: String,
      selected: String
    },
    data () {
      return {
        loading: false,
        tableData: [],
        total: 0,
        pageSize: 10,
        currentPage: 1
      }
    },
    async created () {
      this.immediate && await this.search()
    },
    methods: {
      async search (i, isScroll) {
        this.currentPage = i > 0 ? i : this.currentPage
        let query = JSON.parse(JSON.stringify(this.query))
        for (let key in query) {
          if (Array.isArray(query[key])) {
            query[key] = query[key].toString()
          }
        }
        let req = {
          pageNum: this.currentPage,
          pageSize: this.pageSize,
          ...query
        }
        if(this.isCustomTime){
          let paytime=this.query.payTime || [];
           req.payTimeStart=paytime[0]
           req.payTimeEnd=paytime[1]
        }
        this.loading = true
        if (this.isPost) {
            this.$api.post(this.action, req, r => {
              this.loading = false
              this.handleOperation(r, isScroll)
            })
        } else {
          this.$api.get4(this.action, req, r => {
            this.loading = false
            this.handleOperation(r, isScroll)
          })
        }
      },
      handleOperation (r, isScroll) {
        if (r.flag) {
          this.callback && this.callback(r) // 如果要对返回值做额外操作
          if (this.isSecondLayer) {  // 有分页
            if(r.data.allNum){
               this.total = +r.data.allNum
            }else{
               this.total = +r.data.total
            }
            if (!this.dataList) {  // 如果接口返回的data数据为dataList,根据实际情况而定
              this.tableData = r.data.dataList
            } else {  // 其他参数名时取值
              this.tableData = r.data[this.dataList]
            }
          } else {  // 没有分页
            if (this.isArray) {  // 如果数据类型为数组
              this.tableData = r.data
            } else {   // 如果数据类型为非数组
              this.tableData = []
              this.tableData.push(r.data)
            }
          }
          this.selected && this.handleTest()
          isScroll && this.$refs.table.scrollIntoView({behavior: 'smooth', block: 'start'})
        }
      },
      handleCurrentChange (index) {
        this.search(index, true)
      },
      handleSortChange (val) {
        this.$emit('sortChange', val)
      },
      handleSelectionChange (val) {
        this.$emit('selectionChange', val)
      },
      handleSizeChange (val) {
        this.pageSize = val
        this.search(1, true)
      },
      handleTest () {
        const rows = this.selected.split(',')
        this.tableData.forEach((row, i) => {
          rows.forEach(_ => {
            if (row.id === parseInt(_)) {
              this.$nextTick(() => {
                this.$refs.test.toggleRowSelection(row, true)
              })
            }
          })
        })
      },
      clearSelected () {
        this.$refs.multipleTable.clearSelection()
      }
    }
  }
</script>
<style lang="scss" scoped>
</style>

myTable

参数 说明 类型 默认值
headerBgColor 表头背景色 String white
fixHeight 是否固定表格高度 boolean false
tableH 表格高度(fixHeight为true, 则tableH必须设定) number 0
isShowSelection 是否开启选择功能 boolean false
isShowSerialNumber 是否显示序号 boolean true
isShowOperation 是否显示操作列 boolean true
isShowSummary 是否显示总计 boolean true
fixedType 是否固定右侧操作栏 boolean false
props 列标题以及对应的参数名数组 Array []
tableData 后台返回的数据 Array []
immediate 是否创建即请求数据 boolean true
isShowPagination 是否显示底部的分页器 boolean true
isSecondLayer 是否有分页 boolean true
isPost 是否为post请求 boolean true
isCustomTime 起始时间划分为两个参数的情况 boolean false
isArray 返回数据是否为数组形式 boolean true
query 查询参数 Object { }
action 请求接口 String 必传
dataList 获取data数据的key值 String r.data[dataList]

使用方式:

  • 1、数据结构为非数组,只显示一行的统计类表格
data:{
    redAmount: "632.00"
    people: 3
    gift: 11
}
<template>
  <div>
        <el-date-picker
        style="width:220px;"
        size="small"
        clearable
        value-format="yyyy-MM-dd"
        v-model="searchInfo.time"
        type="daterange"
        :picker-options="$utils.pickerOptions"
        range-separator="至"
        start-placeholder="时间选择"
        end-placeholder="时间选择">
      </el-date-picker>
      <el-button type="primary" size="small" @click="$refs.table.search(1)">查询</el-button>
      <mytable style="padding: 10px;" :isArray="false" :action="action" :query="searchInfo" :props="props" ref="table" :isShowSerialNumber="false" :isShowPagination="false" :isSecondLayer="false" :isShowOperation="false"></mytable>
  </div>
</template>
<script>
export default {
  data() {
    return {
        action: this.$api.baseUrl + 'xxx/xxx/xxxx',
        searchInfo: {
           time: ''
        },
        props: [
        {
          prop: 'uvNum',
          label: '落地页uv'
        },
        {
          prop: 'people',
          label: '红包领取人数'
        },
        {
          prop: 'gift',
          label: '坚果礼包领取人数'
        }
      ],
    };
  },
};
</script>
  • 2、常用统计表
<mytable dataList="records" :fixedType="true" style="padding: 10px;" :action="action1" :query="searchInfo" :props="props1" ref="table1">
            <template #status="{data}">
               <p class="status-reject" v-if="data.status === 0">审核不通过</p>
               <p class="status-pass" v-if="data.status === 1">审核通过</p>
               <p class="status-wait" v-else>未审核</p>
            </template>
            <template #operation="{data}">
              <p class="detail" v-if="!data.status"  @click="statusAction(data,1)">审核通过</p>
              <p></p>
            </template>
</mytable>
<script>
export default {
  data() {
    return {
        action1: this.$api.baseUrl + 'xxx/xxx/xxxx',
        searchInfo: {
           time: ''
        },
        props1: [
        {
          prop: 'uvNum',
          label: '落地页uv'
        },
        {
          prop: 'people',
          label: '红包领取人数'
        },
        {
          prop: 'gift',
          label: '坚果礼包领取人数'
        },
        {
          prop: 'status' ,
          label: '审核状态'
        }
      ],
    };
  },
};
</script>

相关文章

网友评论

      本文标题:如何二次封装el-table

      本文链接:https://www.haomeiwen.com/subject/jpmtfltx.html