有时我们在开发过程中会遇到表格里有合并单元格的需求。
今天以View UI (iview)组件库为例。

1. 打开iview官网-table会发现有合并单元格示例:
在这里插入图片描述
2. 但是在实际项目中,无法做到像上边代码那样通过 rowIndexcolumnIndex 在前端将合并的单元格写死,而是需要根据后台返回给前端的数据进行逻辑判断,决定合并哪些单元格。

(1)比如现在有一个需求是表格的第一列“类别”中,如果有相同类别名字的进行单元格合并

<template>
    <Table :columns="columns1" :data="data1" :span-method="handleSpan"></Table>
</template>
<script>
export default {
data () {
 return {
     columns1: [
         {
             title: '类别',
             key: 'name'
         },
         {
             title: '指标内容',
             key: 'date'
         }
     ],
     data1: [
         {
             name: 'John Brown',
             date: 18,
         },{
             name: 'John Brown',
             date: 18,
         },{
             name: 'John Brown1',
             date: 181,
         },{
             name: 'John Brown2',
             date: 182,
         },{
             name: 'John Brown2',
             date: 182,
         },{
             name: 'John Brown2',
             date: 182,
         },
     ]
 }
},
methods: {
 handleSpan ({ row, column, rowIndex, columnIndex }) {
 }
}
}
</script>

页面如下:
在这里插入图片描述
(2)可知:第1、2行name值相同、第4、5、6行name值相同,下面研究如何合并第1行第1列、第2行第1列以及第4行第1列、第5行第1列、第6行第1列。

这里我们将data中的 data1改为 resData,而将 data1改为空数组,用 resData 模拟后台返回前端的数据.

注意:在合并行时,需要合并的数据必须相临,否则无法合并。这里我们直接将 resData 中需要合并的数据设为相临,即第1、2条以及第4、第5、第6条,在实际项目中这部分可以通过前端或者后端来操作这些数据,排序,使之相邻。

修改后的代码如下所示:

<template>
    <Table :columns="columns1" :data="data1" :span-method="handleSpan"></Table>
</template>
<script>
export default {
data () {
 return {
     columns1: [
         {
             title: '类别',
             key: 'name'
         },
         {
             title: '指标内容',
             key: 'date'
         }
     ],
     resData: [
         {
             name: 'John Brown',
             date: 18,
         },{
             name: 'John Brown',
             date: 18,
         },{
             name: 'John Brown1',
             date: 181,
         },{
             name: 'John Brown2',
             date: 182,
         },{
             name: 'John Brown2',
             date: 182,
         },{
             name: 'John Brown2',
             date: 182,
         },
     ],
     data1: []
 }
},
methods: {
 handleSpan ({ row, column, rowIndex, columnIndex }) {
 }
}
}
</script>

(3)然后对 resData 中的数据进行处理,从而实现 name 值相同的行进行合并。

代码如下(具体说明已在代码块中添加注释):

<template>
    <Table :columns="columns1" :data="data1" :span-method="handleSpan"></Table>
</template>
<script>
export default {
data () {
 return {
     columns1: [
         {
             title: '类别',
             key: 'name'
         },
         {
             title: '指标内容',
             key: 'date'
         }
     ],
     resData: [
         {
             name: 'John Brown',
             date: 18,
         },{
             name: 'John Brown',
             date: 18,
         },{
             name: 'John Brown1',
             date: 181,
         },{
             name: 'John Brown2',
             date: 182,
         },{
             name: 'John Brown2',
             date: 182,
         },{
             name: 'John Brown2',
             date: 182,
         },
     ],
     data1: []
 }
},
methods: {
 handleSpan ({ row, column, rowIndex, columnIndex }) {
 //合并第1列,这里columnIndex==0,根据需求的不同,需要前端写死
      if(columnIndex == 0) {
          //计算合并的行数列数
          let x = row.mergeColumn == 0 ? 0:row.mergeColumn
          let y = row.mergeColumn == 0 ? 0:1
          return [x, y]
      }
  },
  assembleData(data){
      let names = []
      //筛选出不重复的 name值,将其放到 names数组中
     data.forEach(e => {
         if(!names.includes(e.name)){
             names.push(e.name)
         }
     })
     let nameNums = []
     //将names数组中的 name值设置默认合并0个单元格,放到 nameNums中
     names.forEach(e => {
         nameNums.push({name:e,num:0})
     })
      //计算每种 name值所在行需要合并的单元格数
     data.forEach(e => {
       nameNums.forEach(n => {
           if(e.name == n.name){
               n.num++
           }
       })
     })
	//将计算后的合并单元格数整合到 data中
	data.forEach(e => {
	nameNums.forEach(n => {
  	if(e.name == n.name){
      if(names.includes(e.name)){
          e.mergeColumn = n.num
          //删除已经设置过的值(防止被合并的单元格进到这个 if 语句中)
          names.splice(names.indexOf(n.name),1)
      } else {
          //被合并的单元格设置为 0
          e.mergeColumn = 0
      }
  }
})
})
    //将整理后的数据交给表格渲染
     this.data1 = data
  }
},
 mounted(){
    //这里 this.resData即为后台返回的数据
    this.assembleData(this.resData)
  }
 }
</script>

运行结果如下:
在这里插入图片描述
到这里,也就实现了我们想要的效果。

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐