优雅:Element-UI table任意复杂单元格合并处理技巧

用法说明

处理表格单元格合并是很常见的开发需求,el-table官方提供了合并单元格的用法 如下:

根据使用说明很容易写出带有一堆if else 叠加的屎,随着合并条件的嵌套更会屎上加屎

javascript 复制代码
const arraySpanMethod = ({
  row,
  column,
  rowIndex,
  columnIndex,
}) => {
  if (rowIndex % 2 === 0) {
    if (columnIndex === 0) {
      return [1, 2]
    } else if (columnIndex === 1) {
      return [0, 0]
    }
  }
}

来看看哥们的究极无敌解决方案

先从案例说起,代码实现放在最后了,下面是一个很简单的表格,数据结构也列出来了。

javascript 复制代码
const tableData = [
 {
    id: '12987122',
    species:'人类',
    gender:'男',
    age:'10-20',
    name: 'Tom1',
    amount1: '234',
    amount2: '3.2',
    amount3: 10,
  },
  {
    id: '12987123',
    species:'人类',
    gender:'男',
    age:'10-20',
    name: 'Tom1',
    amount1: '165',
    amount2: '4.43',
    amount3: 12,
  },
  //....
]

现在我们按照物种这个维度将物种这一列进行行合并

使用我的合并方案只需要写出如下代码

vue 复制代码
    <template>
        <el-table  :data="tableData"  :span-method="spanMethod">
        //...
        </el-table>
    </template>
    <script  setup>
        //...
        const spanMethod = rowSpan(tableData,'species',['species'])
    </script>

简简单单一行代码搞定,牛逼坏了。

rowSpan接收三个参数

  1. 表格数据项
  2. 第二个参数代表合并的参照维度,如当前例子中传入的'species',表示表格数据中'species'字段相同的数据项应该被合并
  3. 第三个参数用于指定合并单元格被应用于哪一列上

接下来上点强度,此时产品经理提出,所有物种为"人类"的【Amount 1】取值都是234 我们需要按照物种维度,将【Amount 1】这一列进行合并

我们的代码仅仅只需改动一下第三个参数,将单元格合并应用到amount1这一列就行了

js 复制代码
const spanMethod = rowSpan(tableData,'species',['amount1'])

如果要同时合并,speciesamount1,只需要在数组中同时包含这两个字段就ok

js 复制代码
const spanMethod = rowSpan(tableData,'species',['amount1','species'])

继续上强度

为了说明问题,我们稍微调整下表格数据,新增两条数据

这时候产品的需求是:按照物种,进行性别的单元格合并,也就是说,进行性别单元格合并的前提是他们属于同一物种。

还是一行代码搞定,这时候我们只需要简单的修改一下第二个参数即可

js 复制代码
const spanMethod = rowSpan(tableData,'species.gender',['gender'])

参数很直观,没什么好解释的,如果前提条件不断的堆叠,只需要按照这种格式往后面.就完事。

再上强度,此时,除了性别以外,相同物种的单元格也要进行合并。

兵来将挡,再祭出一个杀器,添加一个高阶函数combie即可,具体实现稍后给出。

js 复制代码
const spanMethod = combine(
  rowSpan(tableData,'species.gender',['gender']),
  rowSpan(tableData,'species',['species'])
)

函数实现


需要依赖lodash的groupBy,有需要请自行安装,或者自己手写实现。

rowSpan

js 复制代码
import {groupBy} from 'lodash';
const rowSpan = (list, spanPath, columnNames) => {
  const rowSpanHandler = (list, handledSpanPath) => {
    if (!handledSpanPath) {
      return
    }
    const spanPathList = handledSpanPath.split('.').filter(Boolean)
    const fieldName = spanPathList.shift()
    const groups = Object.values(groupBy(list , fieldName))
    groups.forEach((group) => {
      group.forEach((item, index) => {
        if (spanPathList.length === 0) {
          const resultPath = spanPath.split('.').join('_')
          if (index === 0) {
            item[`span_${resultPath}`] = [group.length, 1]
          } else {
            item[`span_${resultPath}`] = [0, 0]
          }
        } else {
          rowSpanHandler(group, spanPathList.join('.'))
        }
      })
    })
  }
  rowSpanHandler(list, spanPath)
  return ({ row, column }) => {
    if (columnNames.includes(column.property)) {
      return row[`span_${spanPath.split('.').join('_')}`]
    }
  }
}

combine

js 复制代码
const combine = (...funcArr)=>{
  return ({ row, column })=>funcArr.map(item=>item({row, column})).find(Boolean)
}

结语

整篇文章只介绍了单元格的纵向合并,有需要的请参照贴出来的代码自行实现。

相关推荐
道爷我悟了1 小时前
Vue入门-指令学习-v-html
vue.js·学习·html
无咎.lsy1 小时前
vue之vuex的使用及举例
前端·javascript·vue.js
工业互联网专业1 小时前
毕业设计选题:基于ssm+vue+uniapp的校园水电费管理小程序
vue.js·小程序·uni-app·毕业设计·ssm·源码·课程设计
计算机学姐2 小时前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
twins35203 小时前
解决Vue应用中遇到路由刷新后出现 404 错误
前端·javascript·vue.js
qiyi.sky3 小时前
JavaWeb——Vue组件库Element(3/6):常见组件:Dialog对话框、Form表单(介绍、使用、实际效果)
前端·javascript·vue.js
杨荧3 小时前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源
Front思4 小时前
vue使用高德地图
javascript·vue.js·ecmascript
花花鱼7 小时前
@antv/x6 导出图片下载,或者导出图片为base64由后端去处理。
vue.js
流烟默7 小时前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch