使用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] 表示不合并。
相关推荐
Cachel wood19 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
joan_8525 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
还是大剑师兰特1 小时前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
军训猫猫头2 小时前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
wuningw3 小时前
ant-design-ui的Select选择器多选时同时获取label与vaule值
ui·arcgis
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
SoraLuna8 小时前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
燃先生._.9 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js