Antv a-table 表格行/列合并,在合并后的td中使用插槽slot

【需求】

这次的表格需要实现行列合并,并且要在合并后的 td 中使用子组件或弹出弹窗,难点在于:

1. 根据提供的data,自行判断是否合并项的 getRowspan方法 

2. customCell 、scopedSlots 冲突导致的子组件无法展示

(在最下方的参考资料中提供了关于这两个难点的解决方法,感谢两位作者。)

【template】

<template>
  <div style="margin: 20px;">
    <a-table :columns="columns" :data-source="data" bordered>
      <template slot="head3" slot-scope="text"><editable-cell :text="text" /></template>
      <template slot="func4" slot-scope="text, record">
        <a-button v-if="record.func4.length == 0" type="link" @click="handleChoose(record.key)">
          <span>请选择item</span>
        </a-button>
        <a-tooltip v-else placement="topLeft">
          <template slot="title">
            <span style="margin-right: 8px;" v-for="item in record.func4" :key="item">{{ item }}</span>
          </template>
          <a-button type="link" @click="handleChoose(record.key)">
            <span>已选择{{ record.func4.length }}项</span>
          </a-button>
        </a-tooltip>
      </template>
      <template slot="head5" slot-scope="text, record">
        <div v-if="record.slot5.isEdit">
          <editable-cell :text="record.slot5.value" />
        </div>
        <div v-else>
          {{ record.slot5.value }}
        </div>
      </template>
      <template slot="slot6" slot-scope="text">
        <editable-cell :text="text" />
      </template>
      <template slot="action" slot-scope="text,record">
        <div>
          <a-button type="link">link {{ record.key }}</a-button>
        </div>
      </template>
    </a-table>
  </div>
</template>

【script】

<script>
import EditableCell from '@/components/EditableCell';

const data = [
  {
    key: '1',
    name1: 'item1.1',
    name2: 'text1',
    slot3: 'slot1',
    func4: [],
    slot5: {
      isEdit: false,
      value: 'text'
    },
    slot6: 'slot',
    head7: 'text',
  },
  {
    key: '2',
    name1: 'item1.1',
    name2: 'text1',
    slot3: 'slot1',
    func4: [],
    slot5: {
      isEdit: false,
      value: 'text'
    },
    slot6: 'slot',
    head7: 'text',
  },
  {
    key: '3',
    name1: 'item2.1',
    name2: 'text2',
    slot3: 'slot2',
    func4: ['item1', 'item2', 'item3'],
    slot5: {
      isEdit: false,
      value: 'text'
    },
    slot6: 'slot',
    head7: 'text',
  },
  {
    key: '4',
    name1: 'item2.1',
    name2: 'text2',
    slot3: 'slot2',
    func4: ['item1', 'item2', 'item3'],
    slot5: {
      isEdit: true,
      value: 'slot'
    },
    slot6: 'slot',
    head7: 'text',
  },
];

export default {
  components: { EditableCell },
  data() {
    return {
      data,
      columns: [
        {
          title: 'head1',
          dataIndex: 'name1',
          width: 160,
          customCell: (record, rowIndex, column) => {
            return {
              style: { display: this.rowSpanArr[rowIndex] === 0 ? 'none' : undefined },
              attrs: {
                rowSpan: this.rowSpanArr[rowIndex],
              }
            }
          },
        },
        {
          title: 'head2',
          dataIndex: 'name2',
          width: 120,
          customCell: (record, rowIndex, column) => {
            return {
              style: { display: this.rowSpanArr[rowIndex] === 0 ? 'none' : undefined },
              attrs: {
                rowSpan: this.rowSpanArr[rowIndex],
              }
            }
          },
        },
        {
          title: 'head3-slot',
          width: 200,
          dataIndex: 'slot3',
          scopedSlots: { customRender: 'head3' },
          customCell: (record, rowIndex, column) => {
            return {
              style: { display: this.rowSpanArr[rowIndex] === 0 ? 'none' : undefined },
              attrs: {
                rowSpan: this.rowSpanArr[rowIndex],
              }
            }
          },
        },
        {
          title: 'head4-func',
          dataIndex: 'func4',
          scopedSlots: { customRender: 'func4' },
          customCell: (record, rowIndex, column) => {
            return {
              style: { display: this.rowSpanArr[rowIndex] === 0 ? 'none' : undefined },
              attrs: {
                rowSpan: this.rowSpanArr[rowIndex],
              }
            }
          },
        },
        {
          title: 'head5-slot-text',
          dataIndex: 'dataCenter',
          scopedSlots: { customRender: 'head5' },
        },
        {
          title: 'head6',
          dataIndex: 'slot6',
          scopedSlots: { customRender: 'slot6' },
        },
        {
          title: 'head7',
          dataIndex: 'head7',
        },
        {
          title: 'action',
          dataIndex: 'action',
          width: 100,
          scopedSlots: { customRender: 'action' }
        },
      ],
      rowSpanArr: [],
    };
  },
  computed: {},
  mounted() {
    this.rowSpanArr = this.getRowspan(this.data, 'name1') // 关键句,选一个会重复并且多项会一致的属性如 name1,作为判断是否合并的依据
  },
  watch: {

  },
  methods: {
    handleChoose(id) {
      console.log('请选择项,id:', id);      
    },
    getRowspan(dataScroce, filed) {
      let spanArr = [];
      let position = 0;

      dataScroce.forEach((item, index) => {
        if (index === 0) {
          spanArr.push(1);
          position = 0;
        } else {
          //需要合并的地方判断
          if (dataScroce[index][filed] === dataScroce[index - 1][filed]) {
            spanArr[position] += 1;
            spanArr.push(0);
          } else {
            spanArr.push(1);
            position = index;
          }
        }
      });
      return spanArr
    }
  }
};
</script>

【注】

import EditableCell from '@/components/EditableCell';

这个子组件是用官网的可编辑单元格这部分改的,链接:表格 Table - Ant Design Vue (antdv.com)

【参考资料】

Ant Design Vue实现a-table表格单元格合并(列/行合并)_a-table合并单元格-CSDN博客

antd的a-table表格中合并且使用插槽(使用customRender合并出现问题解决方案)_a-table customrender-CSDN博客

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值