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
});
}