使用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] 表示不合并。
相关推荐
还是大剑师兰特37 分钟前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
一只小白菜~44 分钟前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
吖秧吖1 小时前
three.js 杂记
开发语言·前端·javascript
前端小超超1 小时前
vue3 ts项目结合vant4 复选框+气泡弹框实现一个类似Select样式的下拉选择功能
前端·javascript·vue.js
大叔是90后大叔1 小时前
vue3中查找字典列表中某个元素的值
前端·javascript·vue.js