普通视图

发现新文章,点击刷新页面。
昨天以前首页

vue2+vue3 Table表格合并

2026年1月21日 18:47

之前在写表格合并的时候非常痛苦,弄不明白合并的具体逻辑,我这里直接贴上通用方法,只需要配置合并规则就可以了,在这里不扯那么多过程,你完全可以拷贝回去立马能用。

vue2 表格合并

<el-table
      :data="tableData"
     :span-method="(param)=>objectSpanMethod(param,tableData)"
      border
      style="width: 100%">
      <el-table-column
        prop="id"
        label="ID"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名">
      </el-table-column>
      <el-table-column
        prop="amount1"
        sortable
        label="数值 1">
      </el-table-column>
      <el-table-column
        prop="amount2"
        sortable
        label="数值 2">
      </el-table-column>
      <el-table-column
        prop="amount3"
        sortable
        label="数值 3">
      </el-table-column>
    </el-table>
<script>
function filterArray(item) {
  const valueArray = this.rule.filter(prop => {
    return item[prop] === this.data[prop]
  })
  if (valueArray.length === this.rule.length) {
    return true
  } else {
    return false
  }
}
  export default {
    data() {
      return {
        tableData: [{
          id: '12987122',
          name: '王小虎',
          amount1: '234',
          amount2: '3.2',
          amount3: 10
        }, {
          id: '12987123',
          name: '王小虎',
          amount1: '165',
          amount2: '4.43',
          amount3: 12
        }, {
          id: '12987124',
          name: '王小虎',
          amount1: '324',
          amount2: '1.9',
          amount3: 9
        }, {
          id: '12987125',
          name: '王小虎',
          amount1: '621',
          amount2: '2.2',
          amount3: 17
        }, {
          id: '12987126',
          name: '王小虎',
          amount1: '539',
          amount2: '4.1',
          amount3: 15
        }],
        spanRule: {
            rule: {
              0: ['department_name']   //表示第一列的合并规则
            }
      }
      };
    },
    methods: {
      // 表格合并
          objectSpanMethod({ row, column, rowIndex, columnIndex }, item) {
            if (Object.keys(this.spanRule.rule).includes(columnIndex.toString())) {
              // filter验证数组
              const currentTable = {
                rule: this.spanRule.rule[columnIndex],
                data: item[rowIndex]
              }
              // 该单元格是否被合并 true 合并, false : 不合并
              let chooseSpan = false
              if (rowIndex !== 0) {
                chooseSpan = filterArray.call(currentTable, item[rowIndex - 1])
              }
              if (chooseSpan) {
                return {
                  rowspan: 0,
                  colspan: 0
                }
              } else {
                return {
                  rowspan: item.filter(filterArray, currentTable).length,
                  colspan: 1
                }
              }
            }
          },
    }
  };
</script>


vue3 表格合并

vue3 hooks文件内容


// 定义通用类型(支持任意表格数据类型)
export interface TableSpanRule {
    rule: Record<string, string[]>; // 列索引 → 合并字段列表
}

// 表格合并Hook
export function useTableSpan<T = Record<string, any>>(spanRule: TableSpanRule) {

    const filterArray = (
        currentTable: { rule: string[]; data: T },
        item: T
    ): boolean => {
        const valueArray = currentTable.rule.filter((prop) => {
            return item[prop] === currentTable.data[prop];
        });
        return valueArray.length === currentTable.rule.length;
    };

    const objectSpanMethod = (
        param: {
            row: T;
            column: T;
            rowIndex: number;
            columnIndex: number;
        },
        tableData: T[]
    ) => {
        const { columnIndex, rowIndex } = param;
        // 判断当前列是否在合并规则中
        if (Object.keys(spanRule.rule).includes(columnIndex.toString())) {
            const currentTable = {
                rule: spanRule.rule[columnIndex],
                data: tableData[rowIndex]
            };
            let chooseSpan = false;
            // 非第一行时验证是否需要合并
            if (rowIndex !== 0) {
                chooseSpan = filterArray(currentTable, tableData[rowIndex - 1]);
            }
            // 需要合并则隐藏当前单元格,否则设置合并行数
            if (chooseSpan) {
                return {
                    rowspan: 0,
                    colspan: 0
                };
            } else {
                return {
                    rowspan: tableData.filter((i) => filterArray(currentTable, i)).length,
                    colspan: 1
                };
            }
        }
        // 非合并列返回默认值
        return {
            rowspan: 1,
            colspan: 1
        };
    };

    return {
        objectSpanMethod
    };
}

vue3 表格合并

<el-table
      :data="tableData"
     :span-method="(param)=>objectSpanMethod(param,tableData)" //这里非常重要,tableData字段是表格的数据
      border
      style="width: 100%">
      <el-table-column 
        prop="day"
        label="day"
        width="180">
      </el-table-column>
      <el-table-column
        prop="domainName"
        label="domainName">
      </el-table-column>
      <el-table-column
        prop="allPurchaseCount"
        sortable
        label="allPurchaseCount">
      </el-table-column>
      <el-table-column
        prop="allPurchaseValue"
        sortable
        label="allPurchaseValue">
      </el-table-column>
      <el-table-column
        prop="gaAmountUsd"
        sortable
        label="交易额">
      </el-table-column>
    </el-table>
const tableCol = [  //表格列
  {
    label: t('localeAudience.datetime'),
    prop: 'day',
    width: 120,
    sortable: "custom",
    formatter: (row: any, column: any, text: any) => {
      return text || "-";
    },
  },
  {
    label: t('localeAudience.domain'),
    width: 120,
    prop: 'domainName',
    'show-overflow-tooltip': true,
  },
  {
    label: t('localeAudience.allorders'),
    sortable: "custom",
    width: 120,
    prop: 'allPurchaseCount',
  },
  {
    label: t('localeAudience.allamount'),
    sortable: "custom",
    width: 140,
    prop: 'allPurchaseValue',
  },
  {
    label: '交易额',
    sortable: "custom",
    width: 180,
    prop: 'gaAmountUsd',
  },
];
const tableData = [ // 1.表格数据
  {
    day: '2023-08-01',
    domainName: 'example.com',
    allPurchaseCount: 10,
    allPurchaseValue: 1000,
    gaAmountUsd: 500,
  },
  {
    day: '2023-08-01',
    domainName: 'example.com',
    allPurchaseCount: 5,
    allPurchaseValue: 500,
    gaAmountUsd: 250,
  },
  {
    day: '2023-08-02',
    domainName: 'example.com',
    allPurchaseCount: 8,
    allPurchaseValue: 800,
    gaAmountUsd: 400,
  },
];
// 2. 定义列合并规则
const spanRule = {
  rule: {
    0: ['day','domainName','allPurchaseCount','allPurchaseValue'], //表示第1列的合并规则
    1: ['day','domainName','allPurchaseCount','allPurchaseValue'], //表示第2列的合并规则
    2: ['day','domainName','allPurchaseCount','allPurchaseValue'], //表示第3列的合并规则
    3: ['day','domainName','allPurchaseCount','allPurchaseValue'], //表示第4列的合并规则
  }
};

// 3. 使用表格合并Hook
const { objectSpanMethod } = useTableSpan(spanRule);
❌
❌