TypeScript 基于ElementUI Tabel封装的表格组件合并方法

最近为公司做了一个VUE脚手架,采用的技术是vue + TypeScript + element-ui进行封装,这样以后公司就有了一个统一的规范,减少大家做不必要的重复工作,大家就可以直接拿来复用。目前整个一套vue脚手架基本封装完毕,但是还没有对外开源,只是内部使用,后期什么时候开源,我会第一时间在码云笔记上公布。因为我也是第一次使用TypeScript进行开发,一边学习一边使用,所以也是摸着石头过河,有很多不完美的地方还希望大家多多担待,好了废话不多说,直接上代码。

HTML代码:

<template>
    <section class="usermanager">
      <!-- 表格 -->
      <el-table
       :data="data"
       v-loading="loading"
       :element-loading-text="loadtext"
       :element-loading-spinner="loadspinner"
       :element-loading-background="loadbgcolor"
       :highlight-current-row="highlight"
       :border='border'
       :stripe='stripe'
       :span-method="this.mergeF ? this.mergeMethod : this.spanMethod"
       @sort-change="handleSort"
       row-key="name"
       style="width: 100%;">
        <el-table-column :type="type" width="55">
        </el-table-column>
        <template v-for="(item, index) in column">
          <el-table-column
           :key="index"
           :label="item.label"
           :prop="item.prop"
           :show-overflow-tooltip="showtooltip"
           :reserve-selection='true'
           :sortable="sortable"
           ></el-table-column>
        </template>
        <slot></slot>
      </el-table>
      <!--页码-->
      <el-col :span="24" class="toolbar">
        <el-pagination
         layout="total,jumper,prev, pager, next,sizes"
         :current-page="currentPage"
         :page-sizes="pagesizes"
         :page-size="pagesize"
         :total="total"
         @size-change="handleSizeChange"
         @current-change="handleCurrentChange"
         style="float:right;">
        </el-pagination>
      </el-col>
    </section>
</template>

TS部分:

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';

@Component({
    name: 'XTable'
})
export default class XTable extends Vue {
  // ======================props=====================
  // 加载
  @Prop({type:Boolean,default:true}) loading!: boolean;
  // 加载内容
  @Prop({type:String,default: '拼命加载中'}) loadtext!: string;
  // 加载图标类名
  @Prop({type:String,default: 'el-icon-loading'}) loadspinner!: string;
  // 加载背景色值
  @Prop({type:String,default: 'rgba(0, 0, 0, 0.8)'}) loadbgcolor!: string;
  // 边框显示
  @Prop({type: Boolean, default:true}) border!: boolean;
  // 当内容过长被隐藏时显示 tooltip
  @Prop({type: Boolean,default:true}) showtooltip!: boolean;
  // 当前行高亮显示
  @Prop({type:Boolean,default:true}) highlight!: boolean;
  // 对应列的类型
  @Prop({ default: function () {return 'selection'}}) type!: 'selection' | 'index' | 'expand'
  // 表格数据
  @Prop({ type: Array, default: function(){ return [] } }) data!: [];
  //表头数据
  @Prop({ type: Array, default: function(){ return [] } }) column!: [];
  @Prop({ type: Array, default: function(){ return [] } }) merge!: [];
  // 每页显示个数选择器的选项设置
  @Prop({ type: Array, default: function(){ return [] } }) pagesizes!: []
  // 总条目数
  @Prop(Number) total!: Number;
  // 每页显示条目个数,支持 .sync 修饰符
  @Prop({type:Number, default:10}) pagesize!: Number;
  //当前页数,支持 .sync 修饰符
  @Prop(Number) currentPage!: Number;
  // 全选单选
  @Prop({ type: Array, default: function(){ return [] } }) sels!: [];
  // 是否可以排序 三个值可选:true, false, 'custom'
  @Prop({type:[Boolean,String],default:false}) sortable!: boolean;

  @Prop(Function)
  spanMethod?:Function;

  mergeLine: Object = {}
  mergeIndex: Object = {}

  get stripe(): boolean {
    return this.$attrs.stripe !== 'false'
  }
  // ======================created=====================
  created () {
    this.getMergeArr(this.data, this.merge)
  }
  // ======================mounted=====================
  mounted() {
    this.getMergeArr(this.data, this.merge)
    
  }
  // ======================methods=====================
  handleSizeChange (val: number){
    this.$emit('handleSizeChange', val)
  }
  handleCurrentChange(currentPage: number) {
    this.$emit('handleCurrentChange', currentPage)
  }
  handleSort (column:any, prop:any, order:any) {
    this.data.sort((a, b) => {
      return Math.random() - 0.5
    })
  }
  // 合并单元格
  getMergeArr (tableData: any, merge: any) {
    if (!merge) return
    this.mergeLine = {}
    this.mergeIndex = {}
    merge.forEach((item:any, k:any) => {
      tableData.forEach((data:any, i:any) => {
        if (i === 0) {
          (this as any).mergeIndex[item] = (this as any).mergeIndex[item] || [];
          (this as any).mergeIndex[item].push(1);
          (this as any).mergeLine[item] = 0;
        } else {
          if (data[item] === tableData[i - 1][item]) {
            (this as any).mergeIndex[item][(this as any).mergeLine[item]] += 1;
            (this as any).mergeIndex[item].push(0);
          } else {
            (this as any).mergeIndex[item].push(1);
            (this as any).mergeLine[item] = i;
          }
        }
      })
    })
  }
  mergeMethod (obj:{ row:any, column:any, rowIndex:any, columnIndex:any }) {
    const index = (this as any).merge.indexOf(obj.column.property)
    if (index > -1) {
      const _row = this.mergeIndex[this.merge[index]][obj.rowIndex]
      const _col = _row > 0 ? 1 : 0
      return {
        rowspan: _row,
        colspan: _col
      }
    }
  }
  // ======================watch=====================
  @Watch('merge')
  mergeF (): void {
    this.getMergeArr(this.data, this.merge)
  }
  dataLength (): void {
    this.getMergeArr(this.data, this.merge)
  }
}
</script>

然后,我们在父组件内使用x-table进行调用,在上面配置merge,merge为一个包含需要合并的column中prop的数组,配置后会自动将值相同的项自动合并。

<ean-table
     :data="tableData.data"
     :column="tableData.column"
     :merge="['date','province']"
     >
     </ean-table>

最终效果:

TypeScript 基于ElementUI Tabel封装的表格组件合并方法

以上知识提供参考,感谢阅读。

未经允许不得转载:码云笔记 » TypeScript 基于ElementUI Tabel封装的表格组件合并方法
喜欢(3) 打赏

评论抢沙发

评论前必须登录!

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏