el-table 动态合并单元格

634 阅读1分钟

这里提供两种方法,选择适合你的业务场景使用

第一种

  • 效果图

image.png

  • 前端页面简单代码

<el-table
  v-loading="loading"
  border
  :span-method="arraySpanMethod"
  :data="tableData">
  <el-table-column
    prop="projectVo.projectName"
    label="项目名称">
  </el-table-column>
  <el-table-column
    prop="taskTitle"
    label="任务名称">
  </el-table-column>
</el-table>
  • js处理数据的方法

// 获取列表数据
loadSubProject () {
  this.loading = true
  this.parentProjectName = this.$officeCacheUtils.getOfficeName(this.queryParam.executiveDepartmentId, '-')
  this.queryParam.insideParentId = this.projectId
  this.$http({
    url: '/project/project/selectProjectTask',
    method: 'get',
    params: {
      ...this.queryParam
    }
  }).then(({ data }) => {
    if (data && data.success) {
      this.tableData = data.list
      this.mergeProject(data.list)
      this.loading = false
    }
  })
},


// 合并单元格
mergeProject (arr) {
  this.spanObj = []
  var obj = {}
  var k = ''
  let len = arr.length
  for (let i = 0; i < len; i++) {
  // 根据指定列合并
    k = arr[ i ].projectVo.projectName
    if (obj[ k ]) {
      obj[ k ] ++
    } else {
      obj[ k ] = 1
    }
  }
  for (let o in obj) {
    for (let i = 0; i < obj[ o ]; i++) {
      if (i === 0) {
        this.spanObj.push(obj[ o ])
      } else {
        this.spanObj.push(0)
      }
    }
  }
},

// 合并单元格
arraySpanMethod ({ row, column, rowIndex, columnIndex }) {
  if (columnIndex === 0) {
    let _row = this.spanObj[ rowIndex ]
    let _col = this.spanObj[ rowIndex ] > 0 ? 1 : 0
    return {
      rowspan: _row,
      colspan: _col
    }
  }
},

第二种(可以灵活配置)

image.png

  • 实现思路 通过倒序遍历数组,符合条件时使用combineProp进行累加,并设置当前单元格属性rowspan和colspan为0,直到不符合条件后对当前项rowspan进行赋值

  • 前端简单页面

<el-table  
:data="dataList"                                
:span-method="arraySpanMethod"                  
border                                          
style="width: 100%">                            
<template v-for="(item, index) in colDataList"> 
<el-table-column                                
:label="item.label"                             
:prop="item.prop"                               
></el-table-column>                             
</template>                                     
<!-- 增减项 -->                                   
<el-table-column label="操作">                   
<template v-slot="scope">                      
<i class="icons el-icon-circle-plus-outline"   
@click="addRow(scope.row, scope.$index)"></i>  
<i class="icons el-icon-remove-outline"        
@click="delRow(scope.$index)"></i>             
</template>                                    
</el-table-column>                             
</el-table>
  • js方法

methods : {



refreshList () {
  this.loading = true
  this.$http({
    url: '/task/taskInfo/correntionScore',
    method: 'get',
    params: {
      'pageNo': this.pageNo,
      'pageSize': this.pageSize,
      'orderBy': this.orderBy,
      ...this.searchForm
    }
  }).then(({ data }) => {
    if (data && data.success) {
      this.dataList = data.page.list
      // 调用合并的方法
      this.mergeData(this.dataList)
      this.total = data.page.count
      this.loading = false
    }
  })
},

  isEmpty ( val ) {
    return typeof val == 'undefined' || val === null || val == '-'
  } ,
  isObject ( val ) {
    return Object.prototype.toString.call ( val ) === '[object Object]'
  } ,
  arraySpanMethod ( { row , column , rowIndex , columnIndex } ) {
    const span = column[ 'property' ] + '-span'
    if ( row[ span ] ) {
      return row[ span ]
    }
  } ,
 
 
  mergeData ( list ) {
    // mergeTarge - 合并项依据
    // combineProp - 根据mergeTarge 进行合并的单元格属性
    let config = {
      mergeTarget : 'id' , // 通用依据
      combineProp : [
        'id' ,
        'name' ,
        {
          mergeTarget : 'name' ,
          combineProp : ['amount1' , 'amount2']
        } ,
        'amount3'
      ]
    }
    return this.filterData ( config , [].concat ( list ) )
  } ,
  filterData ( config , dataList , targetProp ) {
    const { mergeTarget , combineProp } = config
    // 叠加的合并条件
    combineProp.forEach ( ( column , index ) => {
      // 记录合并项
      let combineCount = 1
      if ( this.isObject ( column ) ) {
        return this.filterData.call ( this , column , dataList , mergeTarget )
      }
      // 使用倒序遍历
      for ( let i = dataList.length - 1 ; i >= 0 ; i -- ) {
        let curr = dataList[ i ] ,
          prev = dataList[ i - 1 ]

        if ( this.isEmpty ( prev ) ) {
          // 已经循环完毕
          curr[ `${ column }-span` ] = {
            rowspan : combineCount ,
            colspan : combineCount >= 1?1:0
          }
          break;
        }

        if ( ( prev[ targetProp ] === curr[ targetProp ] &&
          prev[ mergeTarget ] === curr[ mergeTarget ] ) &&
          prev[ `${ column }` ] === curr[ `${ column }` ]
        ) {

          ++ combineCount;
          curr[ `${ column }-span` ] = {
            rowspan : 0 ,
            colspan : 0
          }

        } else {
          curr[ `${ column }-span` ] = {
            rowspan : combineCount ,
            colspan : combineCount >= 1?1:0
          }
          prev[ `${ column }-span` ] = {
            rowspan : 1 ,
            colspan : 1 ,
          }
          // 前后项不相符时,对combinecount进行重置
          combineCount = 1
        }
      }
    } )
    return dataList
  } ,
} ,
computed : {
  colDataList () {
    return [{
      label : 'ID' ,
      prop : 'id'
    } , {
      label : '姓名' ,
      prop : 'name'
    } , {
      label : '数值1' ,
      prop : 'amount1'
    } , {
      label : '数值2' ,
      prop : 'amount2'
    } , {
      label : '数值3' ,
      prop : 'amount3'
    }]
  }
}