vxe-table vue 表格实现复杂分组列头与数据合并:多级分类与动态合并实战

在商品管理、订单报表等业务场景中,我们常常需要展示多层级分类(如一级分类 → 二级分类 → 三级分类),并希望将相同分类的数据行纵向合并,让表格结构更清晰、数据层级一目了然。vxe-table 提供了灵活的列头分组(children)和单元格合并(mergeCells)机制,可以轻松实现“复杂表头 + 数据自动合并”的效果。

  • 本文将基于一个商品列表示例,详解如何实现:
    • 使用多级列头(分类、商品信息、款式)构建复杂表头。
    • 通过动态计算 mergeCells,自动按分类层级合并数据单元格,并附带一个通用的合并规则计算器,可复用到任何层级字段。

最终效果预览

  • 表头:按“分类”、“商品信息”、“款式”等多级分组,形成清晰的树形表头结构。
  • 数据区:根据“一级分类 → 二级分类 → 三级分类”的层级关系,自动合并相同类别的单元格,使同类数据聚合在一起,提升可读性。

image

代码

  1. 通过在 columns 中使用 children 属性,可以构建无限层级的树形表头:
  2. 动态计算 mergeCells 数据合并规则,为了根据数据自动生成合并规则,我们需要一个递归算法:按 categoryLevel1 → categoryLevel2 → categoryLevel3 的顺序,统计相邻行中相同值的连续行数,生成对应的合并单元。

重要前提:数据必须按层级字段排序(如先按一级分类、再按二级分类、再按三级分类),否则相同类别的行不会连续,合并会错乱。

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

const gridOptions = reactive({
  height: 1000,
  border: true,
  loading: false,
  columnConfig: {
    resizable: true
  },
  mergeCells: [
    { row: 0, col: 0, rowspan: 17, colspan: 1 },
    { row: 0, col: 1, rowspan: 9, colspan: 1 },
    { row: 0, col: 2, rowspan: 3, colspan: 1 }
  ],
  columns: [
    {
      title: '分类',
      children: [
        { field: 'categoryLevel1', title: '一级分类', width: 120 },
        { field: 'categoryLevel2', title: '二级分类', width: 120 },
        { field: 'categoryLevel3', title: '三级分类', width: 120 }
      ]
    },
    {
      title: '商品信息',
      children: [
        { field: 'productName', title: '名称', minWidth: 200 },
        { field: 'sku', title: 'SKU', width: 160 },
        { field: 'price', title: '价格', width: 120 },
        { field: 'quantity', title: '数量', width: 120 },
        { field: 'currency', title: '货币', width: 120 },
        {
          title: '款式',
          children: [
            { field: 'color', title: '颜色', width: 120 },
            { field: 'size', title: '尺寸编码', width: 120 }
          ]
        }
      ]
    },
    { field: 'updateDate', title: '更新时间', width: 120 },
    { field: 'createDate', title: '创建时间', width: 120 }
  ],
  data: []
})

/**
 * 通用表格合并规则计算器
 * @param {Array} list - 数据数组
 * @param {Array} levelKeys - 层级字段名数组
 * @returns {Array} mergeCells 数组
 */
const calculateMergeCells = (list, levelKeys) => {
  const mergeCells = []
  const total = list.length
  if (total === 0 || levelKeys.length === 0) {
    return
  }
  const processGroup = (start, col) => {
    if (col >= levelKeys.length || start >= total) {
      return
    }
    const key = levelKeys[col]
    let end = start
    const value = list[start][key]
    while (end < total && list[end][key] === value) {
      end++
    }
    mergeCells.push({
      row: start,
      col: col,
      rowspan: end - start,
      colspan: 1
    })
    if (col + 1 < levelKeys.length) {
      let i = start
      while (i < end) {
        const nextKey = levelKeys[col + 1]
        const nextValue = list[i][nextKey]
        let j = i
        while (j < end && list[j][nextKey] === nextValue) {
          j++
        }
        processGroup(i, col + 1)
        i = j
      }
    }
  }
  let i = 0
  while (i < total) {
    const key = levelKeys[0]
    const value = list[i][key]
    let j = i
    while (j < total && list[j][key] === value) {
      j++
    }
    processGroup(i, 0)
    i = j
  }
  return mergeCells
}
const loadList = () => {
  gridOptions.loading = true
  setTimeout(() => {
    const list = [
      { id: 10001, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: 'T恤', productName: '纯棉T恤M894', sku: '2345346546', price: 998, quantity: 32, color: '黑色', size: 'XL', currency: 'rmb', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10002, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: 'T恤', productName: '印花T恤J78', sku: '5676575677567', price: 1203, quantity: 42, color: '红色', size: 'M', currency: 'rmb', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10003, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: 'T恤', productName: '圆领T恤V56', sku: '768768678686', price: 123, quantity: 12, color: '白色', size: 'L', currency: 'rmb', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10004, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: '羽绒服', productName: '薄款羽绒服E1243', sku: '4234324324324', price: 300, quantity: 78, color: '灰色', size: 'XXXL', currency: 'usd', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10005, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: '羽绒服', productName: '厚款羽绒服T56435', sku: '435438797', price: 200, quantity: 60, color: '白色', size: 'XXL', currency: 'usd', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10006, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: '短袖', productName: '印花短袖O76', sku: '1232138908900', price: 425, quantity: 86, color: '蓝色', size: 'L', currency: 'rmb', updateDate: '2026-03-05', createDate: '2026-03-20' },
      { id: 10007, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: '短袖', productName: '运动短袖R45', sku: '23454654356889', price: 125, quantity: 77, color: '紫色', size: 'XXXXL', currency: 'usd', updateDate: '2026-11-05', createDate: '2026-11-20' },
      { id: 10008, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: '短袖', productName: '速干短袖R45', sku: '7802354345568', price: 255, quantity: 66, color: '橙色', size: 'L', currency: 'rmb', updateDate: '2026-10-05', createDate: '2026-10-20' },
      { id: 10009, categoryLevel1: '服装', categoryLevel2: '男装', categoryLevel3: '长袖', productName: '纯棉长袖Y7f', sku: '23434665787097', price: 236, quantity: 85, color: '白色', size: 'XXXL', currency: 'usd', updateDate: '2026-02-03', createDate: '2026-02-03' },
      { id: 10010, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: 'T恤', productName: '纯棉T恤C583', sku: '43543556797234', price: 758, quantity: 12, color: '灰色', size: 'L', currency: 'rmb', updateDate: '2026-09-05', createDate: '2026-09-20' },
      { id: 10011, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: 'T恤', productName: '超短T恤K847', sku: '54367567809081243', price: 468, quantity: 14, color: '红色', size: 'XXXL', currency: 'usd', updateDate: '2026-11-02', createDate: '2026-11-02' },
      { id: 10012, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: '长袖', productName: '纯棉长袖V7854', sku: '34565779800867', price: 568, quantity: 25, color: '白色', size: 'L', currency: 'rmb', updateDate: '2026-12-05', createDate: '2026-12-20' },
      { id: 10013, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: '长袖', productName: '运动款长袖J834', sku: '32443216578090534', price: 369, quantity: 24, color: '紫色', size: 'M', currency: 'rmb', updateDate: '2026-08-05', createDate: '2026-08-20' },
      { id: 10014, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: '长袖', productName: '印花长袖C674', sku: '657897124535400', price: 147, quantity: 65, color: '橙色', size: 'XXXXL', currency: 'rmb', updateDate: '2026-06-07', createDate: '2026-05-27' },
      { id: 10015, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: '羽绒服', productName: '超薄羽绒服C743', sku: '2342344567659345', price: 258, quantity: 34, color: '蓝色', size: 'XXXL', currency: 'usd', updateDate: '2027-06-05', createDate: '2027-05-20' },
      { id: 10016, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: '羽绒服', productName: '特厚羽绒服Z746', sku: '122459800980965', price: 80, quantity: 44, color: '黑色', size: 'XXL', currency: 'rmb', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10017, categoryLevel1: '服装', categoryLevel2: '女装', categoryLevel3: '羽绒服', productName: '超轻羽绒服K847', sku: '324324890435356', price: 60, quantity: 55, color: '灰色', size: 'L', currency: 'rmb', updateDate: '2026-07-05', createDate: '2026-07-20' },
      { id: 10018, categoryLevel1: '家电', categoryLevel2: '冰箱', categoryLevel3: '160升', productName: '160升大冰箱H8764', sku: '34657687934256457', price: 2354, quantity: 77, color: '橙色', size: 'XXL', currency: 'usd', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10019, categoryLevel1: '家电', categoryLevel2: '冰箱', categoryLevel3: '160升', productName: '160升省电冰箱D768', sku: '32454366540901', price: 3250, quantity: 81, color: '白色', size: 'M', currency: 'usd', updateDate: '2026-06-01', createDate: '2026-05-05' },
      { id: 10020, categoryLevel1: '家电', categoryLevel2: '冰箱', categoryLevel3: '90升', productName: '90升小冰箱F456', sku: '1214355460980', price: 1000, quantity: 99, color: '黑色', size: 'XXXXL', currency: 'rmb', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10021, categoryLevel1: '家电', categoryLevel2: '冰箱', categoryLevel3: '90升', productName: '90升便捷冰箱H6754', sku: '948239017423743472', price: 3520, quantity: 97, color: '红色', size: 'XXL', currency: 'usd', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10022, categoryLevel1: '家电', categoryLevel2: '洗衣机', categoryLevel3: '滚筒', productName: '高端滚筒洗衣机H847', sku: '1045671345436577', price: 5060, quantity: 10, color: '橙色', size: 'L', currency: 'rmb', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10023, categoryLevel1: '家电', categoryLevel2: '洗衣机', categoryLevel3: '滚筒', productName: '普通滚筒洗衣机B8743', sku: '12000234645456', price: 3250, quantity: 9, color: '紫色', size: 'XXXXL', currency: 'rmb', updateDate: '2026-09-11', createDate: '2026-09-15' },
      { id: 10024, categoryLevel1: '家电', categoryLevel2: '洗衣机', categoryLevel3: '波轮', productName: '家用波轮洗衣机J984', sku: '3804354351435243', price: 5000, quantity: 19, color: '白色', size: 'XXL', currency: 'usd', updateDate: '2026-08-10', createDate: '2026-08-11' },
      { id: 10025, categoryLevel1: '家电', categoryLevel2: '洗衣机', categoryLevel3: '波轮', productName: '高端波轮洗衣机X8734', sku: '948246547367867802', price: 4000, quantity: 29, color: '红色', size: 'M', currency: 'rmb', updateDate: '2026-10-05', createDate: '2026-10-20' },
      { id: 10026, categoryLevel1: '家电', categoryLevel2: '电视', categoryLevel3: '85寸', productName: '85寸超级电视机G456', sku: '32345450039083456', price: 9000, quantity: 5, color: '紫色', size: 'XXXL', currency: 'usd', updateDate: '2026-06-05', createDate: '2026-05-20' },
      { id: 10027, categoryLevel1: '家电', categoryLevel2: '电视', categoryLevel3: '85寸', productName: '85寸标准电视H874', sku: '890345081232340009', price: 7000, quantity: 37, color: '红色', size: 'M', currency: 'usd', updateDate: '2026-11-10', createDate: '2026-11-22' },
      { id: 10028, categoryLevel1: '家电', categoryLevel2: '电视', categoryLevel3: '80寸', productName: '80寸纳米电视机H763', sku: '213042456456798034', price: 6000, quantity: 3, color: '灰色', size: 'XXL', currency: 'rmb', updateDate: '2026-02-19', createDate: '2026-02-22' },
      { id: 10029, categoryLevel1: '家电', categoryLevel2: '电视', categoryLevel3: '80寸', productName: '80寸超级音质电视机B704', sku: '235768765876584304', price: 5000, quantity: 2, color: '白色', size: 'L', currency: 'rmb', updateDate: '2026-01-05', createDate: '2026-01-20' },
      { id: 10030, categoryLevel1: '家电', categoryLevel2: '电视', categoryLevel3: '65寸', productName: '65寸小电视机V650', sku: '561231234345600', price: 4500, quantity: 14, color: '蓝色', size: 'L', currency: 'rmb', updateDate: '2026-06-20', createDate: '2026-05-28' }
    ]
    gridOptions.mergeCells = calculateMergeCells(list, ['categoryLevel1', 'categoryLevel2', 'categoryLevel3'])
    gridOptions.data = list
    gridOptions.loading = false
  }, 150)
}

loadList()
</script>

配置要点

配置项 作用 本例中的值
columns[].children 构建多级表头 分类 → 商品信息 → 款式,共三层
mergeCells 定义数据单元格合并规则 由 calculateMergeCells 动态生成
columnConfig.resizable 允许用户拖拽调整列宽 true

注意事项

问题 原因 解决方案
合并区域错位或重叠 数据未按层级字段排序 对数据按 levelKeys 顺序排序后再传入。
部分层级未合并 levelKeys 未包含该字段 检查传入的 levelKeys 数组是否完整。
合并后某些行显示空白 rowspan 计算超出数据边界 检查 processGroup 中的 end 值是否超过 total。
表头与数据错位 children 层级与合并列数不匹配 确保 mergeCells 中的 col 索引与 columns 中的叶子列索引对应。
性能问题(数据量大时卡顿) calculateMergeCells 递归遍历复杂度较高 可在数据加载后单独计算,避免在渲染循环中频繁调用。

通过 vxe-table 的多级列头(children)和单元格合并(mergeCells)功能,我们可以轻松实现商品分类等复杂表格的分组展示;这种方法不仅适用于商品分类,还可用于部门组织架构、地区分级等任何需要层级合并的场景。

https://vxetable.cn

posted @ 2026-08-03 14:36  独行者r2  阅读(0)  评论(0)    收藏  举报