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 封装的表格组件合并方法

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

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » TypeScript 基于ElementUI Tabel封装的表格组件合并方法

发表回复