使用element UI实现表格行/列合并

前言

本文代码使用vue2+element UI,通过给table传入span-method方法实现合并行或列

效果图

示例代码

后端返回数据格式如下

javascript 复制代码
{
  "total": 12,
  "records": [
    [
      {
        "id": 1,
        "project": "田径",
        "subitem": "100米",
        "category": "决赛",
        "score": 9.6,
        "creator": "张三",
        "competitionName": "国际田联锦标赛",
        "date": "2023-08-15",
        "location": "北京",
        "worldRecord": "1",
        "asiaRecord": "0"
      },
      {
        "id": 2,
        "project": "田径",
        "subitem": "100米",
        "category": "资格赛",
        "score": 10.1,
        "creator": "李四",
        "competitionName": "全国田径锦标赛",
        "date": "2023-09-01",
        "location": "上海",
        "worldRecord": "0",
        "asiaRecord": "0"
      }
    ],
    [
      {
        "id": 3,
        "project": "田径",
        "subitem": "200米",
        "category": "决赛",
        "score": 19.2,
        "creator": "王五",
        "competitionName": "国际田联锦标赛",
        "date": "2023-08-15",
        "location": "北京",
        "worldRecord": "1",
        "asiaRecord": "0"
      },
      {
        "id": 4,
        "project": "田径",
        "subitem": "200米",
        "category": "资格赛",
        "score": 20.5,
        "creator": "赵六",
        "competitionName": "全国田径锦标赛",
        "date": "2023-09-01",
        "location": "上海",
        "worldRecord": "0",
        "asiaRecord": "0"
      }
    ],
    [
      {
        "id": 15,
        "project": "田径",
        "subitem": "跳远",
        "category": "决赛",
        "score": 8.4,
        "creator": "马十三",
        "competitionName": "国际田联锦标赛",
        "date": "2023-08-15",
        "location": "北京",
        "worldRecord": "0",
        "asiaRecord": "1"
      },
      {
        "id": 16,
        "project": "田径",
        "subitem": "跳远",
        "category": "资格赛",
        "score": 7.8,
        "creator": "李十四",
        "competitionName": "全国田径锦标赛",
        "date": "2023-09-01",
        "location": "上海",
        "worldRecord": "0",
        "asiaRecord": "0"
      }
    ]
  ]
}

分析后端返回数据 :

records 是一个 二维数组, 而 el-table 的 data 属性通常期望的是 一维数组。

所以需要将records中的二维数组 扁平化为一维数组,再赋值。

代码如下

javascript 复制代码
<template>
  <div class="record-manage-container">
   
        <el-table :data="recordList" :span-method="mergeCells">
            <el-table-column prop="project" label="项目" width="180" />
            <el-table-column prop="subitem" label="小项" width="180"/>              
            <el-table-column prop="category" label="类别" />
            <el-table-column prop="score" label="成绩" />
            <el-table-column prop="creator" label="创造者" />
            <el-table-column prop="competitionName" label="比赛名称" />
            <el-table-column prop="date" label="日期" />
            <el-table-column prop="location" label="地点" />
            <el-table-column prop="worldRecord" label="世界纪录" />
            <el-table-column prop="asiaRecord" label="亚洲纪录" />
            
        </el-table>

  </div>
</template>

<script>
import { recordList } from "@/api/game/scoreManage";
export default {
  data() {
    return {
      recordList:[],

     
    };
  },
  created() {
    this.getRecordList()
  },
  methods: {
    // 获取纪录列表
    getRecordList() {
      // 在此处调用获取数据的接口
      recordList().then(res => {
        // console.log(res)
        // 扁平化 records 为一维数组
        this.recordList = res.records.flat()
        this.total = res.total
      })
    },

    mergeCells({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        // 合并 "项目" 列
        const project = row.project;
        const prevProject = rowIndex > 0 ? this.recordList[rowIndex - 1].project : null;
        if (project === prevProject) {
          // 当前项目与上一行项目相同,隐藏当前单元格
          return [0, 0];
        } else {
          // 当前项目与上一行不同,计算合并行数
          const spanCount = this.recordList.filter(item => item.project === project).length;
          return [spanCount, 1]; // 合并 `spanCount` 行,列合并为 1
        }
      }

      if (columnIndex === 1) {
        // 合并 "小项" 列
        const subitem = row.subitem;
        const prevSubitem = rowIndex > 0 ? this.recordList[rowIndex - 1].subitem : null;
        if (subitem === prevSubitem) {
          return [0, 0];
        } else {
          const spanCount = this.recordList.filter(item => item.subitem === subitem).length;
          return [spanCount, 1];
        }
      }

      // 其他列不合并,返回默认值
      return [1, 1];
    },

    
  }
};
</script>

<style lang="scss" scoped>
.record-manage-container {
    padding: 20px;

    .title{
        font-size: 24px;
        font-weight: bold;
    }
}
</style>

分析

  1. res.records.flat():将 records 中的二维数组扁平化为一维数组。例如:
javascript 复制代码
const records = [
  [{ id: 1 }, { id: 2 }],
  [{ id: 3 }, { id: 4 }]
];
const flattened = records.flat();
console.log(flattened); // [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]
  1. mergeCells()方法的实现逻辑

合并"项目"列 (columnIndex === 0):

  • 判断当前行与上一行的项目 (project) 是否相同。
  • 如果相同,返回 [0, 0],表示隐藏当前单元格,因为它会被上一个单元格合并。
  • 如果不同,则计算相同项目的行数 spanCount,返回 [spanCount, 1],表示合并 spanCount 行,列合并为 1。

合并"小项"列 (columnIndex === 1):

  • 判断当前行与上一行的小项 (subitem) 是否相同。
  • 如果相同,返回 [0, 0],隐藏当前单元格。
  • 如果不同,计算相同小项的行数 spanCount,返回 [spanCount, 1]。

默认情况:

  • 对于其他列(比如类别、成绩、创造者等),不需要进行合并,直接返回 [1, 1] 表示不合并。
相关推荐
专业程序开发源26 分钟前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
专业程序开发源39 分钟前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
凤城老人1 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)1 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan2 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_2 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
星光开发者3 小时前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express
传奇开心果编程3 小时前
【ArkUI进阶练中学】第11课:安全与合规进阶
学习·ui·华为·harmonyos
yivifu3 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
vx_Biye_Design4 小时前
springboot高校选课系统82776-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express