You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AntD Table如何使用rowSpan实现嵌套JSON数据跨行合并展示

AntD Table 跨行合并实现方案

问题根因

当前实现直接将嵌套数组的所有内容通过map渲染到单个单元格内,未将嵌套的层级数据拆解为表格独立行,无法触发rowSpan的跨行合并逻辑。AntD Table的单元格合并是通过给单元格DOM设置rowSpan/colSpan属性实现的,必须先将嵌套结构拍平为一维行数据,再给需要合并的单元格配置对应跨行数值,无需显示的重复单元格直接设置rowSpan: 0即可自动隐藏。

具体实现步骤

  • 第一步:预处理数据源,拍平嵌套结构
    原始数据中单个套餐对应多个运营商,单个运营商对应多档API佣金规则,需要把每一档规则拆成独立的表格行,同时提前计算好每一列需要合并的行数:
    import { useMemo } from 'react';
    import { Table } from 'antd';
    import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
    
    // 假设rawDataSource是你传入的原始JSON数据
    const flatDataSource = useMemo(() => {
      const flatList = [];
      rawDataSource.forEach(packageItem => {
        // 计算当前套餐总共占多少行 = 旗下所有运营商的API档位数量总和
        const packageTotalRows = packageItem.providerOperatorCommissionInfos.reduce(
          (total, operator) => total + operator.apiSlabs.length,
          0
        );
        let packageRowIndex = 0; // 标记套餐列当前渲染到第几行,第一行设置全量rowSpan,其余行设0
    
        packageItem.providerOperatorCommissionInfos.forEach(operatorItem => {
          const operatorTotalRows = operatorItem.apiSlabs.length;
          let operatorRowIndex = 0; // 标记运营商列当前渲染到第几行,第一行设置对应rowSpan,其余行设0
    
          operatorItem.apiSlabs.forEach(slabItem => {
            flatList.push({
              key: `${packageItem.packageName}-${operatorItem.operatorName}-${slabItem.min}-${slabItem.max}`,
              packageName: packageItem.packageName,
              operatorName: operatorItem.operatorName,
              operatorCategory: operatorItem.operatorCategory,
              slabMin: slabItem.min,
              slabMax: slabItem.max,
              commissionAmount: slabItem.commission,
              amountType: slabItem.amountType,
              commissionType: slabItem.commissionType,
              gst: slabItem.gst,
              tds: slabItem.tds,
              // 存储各列的合并配置
              packageColSpan: packageRowIndex === 0 ? packageTotalRows : 0,
              operatorColSpan: operatorRowIndex === 0 ? operatorTotalRows : 0,
              actionColSpan: packageRowIndex === 0 ? packageTotalRows : 0
            });
            packageRowIndex++;
            operatorRowIndex++;
          })
        })
      })
      return flatList;
    }, [rawDataSource])
    
  • 第二步:改写columns配置,通过onCell属性设置单元格rowSpan
    移除原来render函数里的嵌套map逻辑,每个单元格直接读取当前行的对应字段渲染即可:
    const columns = [
      {
        title: 'Package Name',
        dataIndex: 'packageName',
        align: 'center',
        onCell: (record) => ({ rowSpan: record.packageColSpan })
      },
      {
        title: 'Operator',
        align: 'center',
        render: (_, record) => (
          <div className="cell-wrap">
            <p>{record.operatorName}</p>
            <p>({record.operatorCategory})</p>
          </div>
        ),
        onCell: (record) => ({ rowSpan: record.operatorColSpan })
      },
      {
        title: 'API Slab',
        align: 'center',
        render: (_, record) => `[${record.slabMin}-${record.slabMax}]`
      },
      {
        title: 'Commission',
        children: [
          {
            title: 'Amount',
            align: 'center',
            render: (_, record) => `${record.commissionAmount} ${record.amountType === 'FIXED' ? '₹' : '%'}`
          },
          {
            title: 'C/S',
            align: 'center',
            render: (_, record) => record.commissionType[0]
          }
        ]
      },
      {
        title: 'GST',
        dataIndex: 'gst',
        align: 'center'
      },
      {
        title: 'TDS',
        dataIndex: 'tds',
        align: 'center'
      },
      {
        title: 'Actions',
        align: 'center',
        render: () => (
          <div className="action-wrap">
            <EditOutlined />
            <DeleteOutlined style={{ marginLeft: 15 }} />
          </div>
        ),
        onCell: (record) => ({ rowSpan: record.actionColSpan })
      }
    ];
    
  • 第三步:将拍平后的flatDataSource传入Table组件的dataSource属性即可
    <Table columns={columns} dataSource={flatDataSource} bordered />
    

效果参考

  • 预期实现效果:
    预期跨行合并表格效果
  • 原有错误渲染效果:
    当前错误渲染效果

注意事项

  • rowSpan设为0时AntD会自动隐藏当前单元格,不会出现内容重复渲染的问题
  • 拍平数据时必须给每一行设置全局唯一的key,否则会出现渲染错位、状态异常的问题
  • 不要在单个单元格的render函数里循环渲染多行内容,跨行效果完全由rowSpan属性控制,每个单元格只需要渲染当前行对应的单份内容

内容的提问来源于stack exchange,提问作者chaoviper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 23:54:32