Vue3 Antd 父子嵌套子表格

父子嵌套子表格

目标1:可以点击多个父节点表格,正确显示子表格数据

目标2:父表格数据刷新重载,解决子表格数据不刷新问题

官方示例代码,以及效果
https://www.antdv.com/components/table-cn#components-table-demo-nested-table
在这里插入图片描述
可以看到官方示例十分简单,使用了 <template #expandedRowRender> 插槽效果,并没有后续的示例

 <template #expandedRowRender>
      <a-table :columns="innerColumns" :data-source="innerData" :pagination="false">
        <template #bodyCell="{ column }">
          <template v-if="column.key === 'state'">
            <span>
              <a-badge status="success" />
              Finished
            </span>
          </template>
          <template v-else-if="column.key === 'operation'">
            <span class="table-operation">
              <a>Pause</a>
              <a>Stop</a>
              <a-dropdown>
                <template #overlay>
                  <a-menu>
                    <a-menu-item>Action 1</a-menu-item>
                    <a-menu-item>Action 2</a-menu-item>
                  </a-menu>
                </template>
                <a>
                  More
                  <down-outlined />
                </a>
              </a-dropdown>
            </span>
          </template>
        </template>
      </a-table>
    </template>

解决方案

使用@expand事件解决

     <a-table @expand="rowExpand" :loading="tableLoading" @change="tableChange"
                   :pagination="tablePagination" :columns="columns" :data-source="financeData"
                   :scroll="{ x: 1300, y: 1000 }" class="components-table-demo-nested"
                   :rowKey="(record,index)=>{return record.id}" bordered>
            <template  #expandedRowRender="{record}">
              <a-table :columns="innerColumns" :data-source="innerDataMap[record.id]" :rowKey="(record,index)=>{return record.id}"
                       :pagination="false">
              </a-table>
            </template>
              <span class="table-operation" @click="handleFinance(record)">
                <a-button type="link">处理
                 <template #icon><EditTwoTone/></template>
                </a-button>
              </span>
            </template>
          </a-table>

在这里插入图片描述

首先我们需要一个const expandedRowKeys = ref([]) 一个列表临时存储点击展开的节点。

@expand=“rowExpand” 方法,监听展开的节点,把节点添加到缓存对象中

    function rowExpand(isExpand, record) {
      //提前为map.key =value 初始化一个空数组
      if (!innerDataMap.value[record.id]) {
        innerDataMap.value[record.id] = [];
      }

      if (isExpand) {
        // 将展开的行的 id 添加到 expandedRowKeys 数组中
        expandedRowKeys.value.push(record.id);

        // 将对应的子表格数据添加到 innerDataMap 中
        innerDataMap.value[record.id] = record.clist;
      } else {
        // 将展开的行的 id 从 expandedRowKeys 数组中删除
        const index = expandedRowKeys.value.indexOf(record.id);
        if (index > -1) {
          expandedRowKeys.value.splice(index, 1);
        }

        // 将对应的子表格数据从 innerDataMap 中删除
        delete innerDataMap.value[record.id];
      }

    }

可以看到嵌套子表格使用innerDataMap是一个Map而不是List,好处是,表格行数据更新,或者点击表格上方查询表格时,可以根据Map[Key]的方式刷新子表格数据

        <template  #expandedRowRender="{record}">
              <a-table :columns="innerColumns" :data-source="innerDataMap[record.id]" :rowKey="(record,index)=>{return record.id}"
                       :pagination="false">
              </a-table>
            </template>

点击处理按钮,修改当前父表格下子表格数据,这时候需要回调reload()重新加载表格,由于使用expandedRowKeys参数记录展开节点,只需要在请求父表格接口时候遍历更新innerDataMap容器就可以了。

reload(){
    queryIList(toData)
      .then((res) => {
        financeData.value = res['list']
        tablePagination.total = res.totalCount
        // 获取当前展开的所有行的 ID
        const expandedRowIds = expandedRowKeys.value;

        // 遍历展开的行,更新对应的子表格数据
        expandedRowIds.forEach(id => {
          const record = financeData.value.find(record => record.id === id);
          if (record) {
            innerDataMap.value[id] = record.clist;
          }
        });
      })
      .catch((e) => {
        console.log('e', e);
      }).finally(() => {
      tableLoading.value = false
});

}
Logo

前往低代码交流专区

更多推荐