使用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-tabledata 属性通常期望的是 一维数组。

所以需要将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] 表示不合并。
相关推荐
毕业设计70312 小时前
(免费领源码) 基于微信小程序的预制菜商城的设计与实现25172-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
vue.js·python·mysql·微信小程序·pycharm·微信开发者工具·推荐算法
xifangge202512 小时前
AGENTS.md 怎么写?涵盖 Java、Python、Vue、Go 的 8 套开箱即用模板
java·vue.js·python
雪芽蓝域zzs13 小时前
vue解构平铺VS对象包裹
前端·javascript·vue.js
默_笙16 小时前
🚲 从写信到打电话:WebSocket 双工通信与跨域方案的"通信进化史"
前端·javascript
ikoala16 小时前
DeepSeek 官方仓库惊现 DeepSeek Harness 桌面端!
前端·javascript·后端
liangshanbo121517 小时前
React useEffect 与 useLayoutEffect 面试题整理
前端·javascript·react.js
Bs_MoneyMagnet17 小时前
基于springboot+vue的旅游景区点评系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·旅游
ID346107442017 小时前
【课程设计】基于Spring Boot+Vue的校园共享无人机服务系统设计与实现-计算机毕设 附源码44219
javascript·vue.js·spring boot·python·node.js·php·课程设计
夜不会漫长17 小时前
C++:类和对象(2)
java·javascript·c++
BillKu18 小时前
Vue3 可拖拽分栏布局:两种实现方式详解
javascript·vue.js·ecmascript