ant design vue 表格 动态合并单元格

1,555 阅读2分钟

需求: 如果 姓名name这一列值相同 则动态合并单元格

效果图: image.png

data1 数据源,要求相同数据必须连续

vue代码段:

   <a-table :columns="column2" :data-source="data1" bordered>
      <template #bodyCell="{ column, text }">
        <template v-if="column.dataIndex === 'action'">
          <a @click="delet">删除</a>
        </template>
      </template>
    </a-table>

js代码段:

<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
  name: '',
  props: {},
  emits: [],
  setup(props, { attrs, slots, emit, expose }) {
    const column2 = ref([
      {
        title: 'Name',
        dataIndex: 'name',
        customCell: (record, index, column) => {
          // colSpan 列合并;rowSpan 行合并
          // 上一行该列数据是否一样(index!==0 从第二行开始,与上一行进行比较)
          if (index !== 0 && record.name === data1.value[index - 1]['name']) {
            return {
              rowSpan: 0, // 表示不渲染
            };
          }
          // 判断下一行是否相等
          let rowSpan = 1;
          for (let i = index + 1; i < data1.value.length; i++) {
            if (record.name !== data1.value[i]['name']) {
              break;
            }
            rowSpan++;
          }
          return {
            rowSpan: rowSpan,
          };
        },
        // customCell: getRowSpan,
      },
      {
        title: 'Age',
        dataIndex: 'age',
      },
      {
        title: 'Phone',
        dataIndex: 'phone',
      },
      {
        title: '操作',
        dataIndex: 'action',
      },
    ]);
    // 要求返回的相同数据必须连续
    const data1 = ref([
      {
        key: '1',
        name: 'John Brown',
        age: 32,
        phone: 18889898989,
      },
      {
        key: '2',
        name: 'John Brown',
        phone: 18889898888,
        age: 42,
      },
      {
        key: '3',
        name: 'Jim Red1',
        age: 32,
        phone: 18900010002,
      },
      {
        key: '4',
        name: 'Jim Red1',
        age: 18,
        phone: 18900010002,
      },
      {
        key: '5',
        name: 'John Brown',
        age: 18,
        phone: 18900010002,
      },
    ]);

    const getRowSpan = (record, index, column) => {
      // 链接: https://www.ngui.cc/article/show-372247.html
      // 上一行该列数据是否一样
      //   if (
      //     record.name !== '' &&
      //     index !== 0 &&
      //     record.name === data1.value[index - 1]['name']
      //   ) {
      //     return {
      //       rowSpan: 0,
      //     };
      //   }
      //   let rowSpan = 1;
      //   // 判断下一行是否相等
      //   for (let i = index + 1; i < data1.value.length; i++) {
      //     if (record.name !== data1.value[i]['name']) {
      //       break;
      //     }
      //     rowSpan++;
      //   }
      //   return {
      //     rowSpan: rowSpan,
      //   };
    };

    return {
      column2,
      data1,
      getRowSpan,
    };
  },
});
</script>

另一种方法: :span-method="objectSpanMethod"

objectSpanMethod方法:

   objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      console.log("objectSpanMethod", row, column, rowIndex, columnIndex);
      if (
        columnIndex === 0 ||
        columnIndex == 1 ||
        columnIndex == 2 ||
        columnIndex == 3 ||
        columnIndex == 4 ||
        columnIndex == 5 ||
        columnIndex == 6 ||
        columnIndex == 13
      ) {
        // 要合并列的下标 从0开始 如果合并第3列 写columnIndex===2
        const _row = this.flitterData(this.tableData).one[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return {
          rowspan: _row,
          colspan: _col,
        };
      }
    },

filterData方法:

  flitterData(arr) {
      // 合并表格第一列
      const spanOneArr = [];
      let concatOne = 0;
      arr.forEach((item, index) => {
        if (index === 0) {
          spanOneArr.push(1);
        } else {
          // 这里的type_test是表格绑定的字段,也就是需要合并的字段,根据自己的需求来改
          if (item.orderId == arr[index - 1].orderId) {
            // 第一列需合并相同内容的判断条件
            spanOneArr[concatOne] += 1;
            spanOneArr.push(0);
          } else {
            spanOneArr.push(1);
            concatOne = index;
          }
        }
      });
      return {
        one: spanOneArr,
      };
    },