Vue3 combined ant.design component Table nested table, get data from backend and render dynamically

When using the nested tables in ant.design according to the official documents, I found that many places in the official documents are not detailed enough. In the process, I stepped on a lot of pitfalls, such as:

How does the child table get the data of the parent table?

How to get row index of child table?

How to make the data source of the child table come from the data of the row of the parent table?

In short, I still stumbled and finished the function in the end, so I sorted out the code for sharing at the first time.

First, the data returned by the backend is in json format.

The data format returned by the backend is as follows:

{
    "result": true,
    "errorCode": null,
    "errorMsg": null,
    "data": [
        {
            "id": "001",
            "name": "A",
            "releaseVersion": "v2.00.02",
            "subSystem": "a",
            "type": "edit",
            "history": [
                {
                    "editVersion": 1,
                    "timestamp": "2023/05/08 12:23",
                    "comment": "备注1.1"
                },
                {
                    "editVersion": 2,
                    "timestamp": "2023/05/08 12:23",
                    "comment": "备注1.2"
                }
            ]
        },
        {
            "id": "002",
            "name": "B",
            "releaseVersion": "v2.00.01",
            "subSystem": "b",
            "type": "edit",
            "history": [
                {
                    "editVersion": 1,
                    "timestamp": "2023/05/08 12:23",
                    "comment": "备注2.1"
                },
                {
                    "editVersion": 2,
                    "timestamp": "2023/05/08 12:23",
                    "comment": "备注2.2"
                }
            ]
        }
    ],
    "recordsTotal": 123
}

The data format for front-end rendering is as follows:

[
    {
        "key": 0,
        "name": "A",
        "subSystem": "a",
        "type": "edit",
        "expand": " ",
        "innerDatas": [
            {
                "key": 0,
                "ID": "001",
                "version": "v2.00.021",
                "editComment": "备注1.1",
                "editTime": "2023/05/08 12:23",
                "more": " "
            },
            {
                "key": 0,
                "ID": "001",
                "version": "v2.00.022",
                "editComment": "备注1.2",
                "editTime": "2023/05/08 12:23",
                "more": " "
            }
        ]
    },
    {
        "key": 1,
        "name": "B",
        "subSystem": "b",
        "type": "edit",
        "expand": " ",
        "innerDatas": [
            {
                "key": 1,
                "ID": "002",
                "version": "v2.00.011",
                "editComment": "备注2.1",
                "editTime": "2023/05/08 12:23",
                "more": " "
            },
            {
                "key": 1,
                "ID": "002",
                "version": "v2.00.012",
                "editComment": "备注2.2",
                "editTime": "2023/05/08 12:23",
                "more": " "
            }
        ]
    }
        ]

code:

<template>

    <div id="main">

        <a-table>

            <template #expandedRowRender="{record}"> 
//这一行代码的意思是添加了一个插槽,#expandedRowRender="{record, index, indent, expanded}",template里面的元素可以使用大括号内的值。其中record是父表内一行的数据,index是行的索引,indent是缩进,expanded表示是否展开。

                <div class="child">

                    <a-table :columns="innerColumns" :data-source="record.innerDatas" >


//表示子表的数据源来自父表record一行数据的innerDatas

                        <template #bodyCell="{ text, record, index, column}"> 
//text表示该行该列也就是这个单元格内的值,record表示子表一行的数据,index表示子表行的索引,column表示子表的列。同样的,该插槽放在父表内表示的就是父表的数据。

                            <template v-if="column.key === 'more'"> 
//这表示子表里column.key为more的这一列,都显示“详细”

                                   <a @click="cilikRow = index, modalVisible = cilikRow > -1" >

                                    详细

                                </a>

                            </template>

                        </template>

                    </a-table>

                    <div class="createModel" ref="createModel">

                        <a-modal v-model:visible="modalVisible" title=" ">

                            <p class="modal-editComment">{
   
   { dataList[0].innerDatas[cilikRow.valueOf()].editComment }}</p> 


//一个a-modal弹窗,当点击“详细”时显示子表中editComment的内容

                        </a-modal>

                    </div>

                </div>

            </template>

        </a-table>

    </div>

</template>

<script lang="ts">

import { DownOutlined } from '@ant-design/icons-vue';

import { defineComponent } from 'vue';

import axios from 'axios';



const cilikRow = ref<Number>(-1)

const columns = [ //父表的列设置

    { title: '标题', dataIndex: 'name', key: 'name', className: 'thChange', width: 400 },

    { title: '副标题', dataIndex: 'subSystem', key: 'subSystem', className: 'thChange', width: 400 },

    { title: '类型', dataIndex: 'type', key: 'type', className: 'thChange', width: 550 },

    { title: '  ', dataIndex: 'expand', key: 'expand', className: 'thChange', expandFixed: 'right' },

];

const innerColumns = [ //子表的列设置

    { title: 'ID', dataIndex: 'ID', key: 'ID', className: 'thColor', width: 100 },

    { title: '版本', dataIndex: 'version', key: 'version', width: 100 },

    { title: '编辑备注', dataIndex: 'editComment', key: 'editComment', ellipsis: true, width: 250 },

    { title: '编辑日期', dataIndex: 'editTime', key: 'editTime', width: 150 },

    { title: '', dataIndex: 'more', key: "more" }

];

interface DataItem { //父表的数据类型定义,我在这里直接把子表的内容放在了父表中

    key: number;

    name: string;

    subSystem: string;

    type: string;

    expand: any;

    innerDatas: innerDataItem[]

}

interface innerDataItem { //子表的数据类型定义

    key: number;

    ID: string;

    version: string;

    editComment: string;

    editTime: string;

    more: string

}

let innerData= reactive<Array<innerDataItem>>([])  //定义一个innerDataItem类型的响应式数组存放子表的数据

const dataList = reactive<Array<DataItem>>([]) //定义一个DataItem类型的响应式数组存放父表的数据

axios.get('http://127.0.0.0/Test/Test123.json')

    .then((res) => {

        for (let i = 0; i < res.data.data.length; i++) {

            innerData = [];    //每次循环将子表数据清空 确保子表数组中的只有父表这一行对应的子表数据而不是子表所有的数据

            for (let j = 0; j < res.data.data[i].history.length; j++) { //子表数据存入

                    innerData.push({

                        key: i,

                        ID: res.data.data[i].id,

                        version: res.data.data[i].releaseVersion + res.data.data[i].history[j].editVersion,

                        editComment: res.data.data[i].history[j].comment,

                        editTime: res.data.data[i].history[j].timestamp,

                        more: " "

                    })

                }



            dataList.push({ //父表数据存入

                key: i,

                name: res.data.data[i].name,

                subSystem: res.data.data[i].subSystem,

                type: res.data.data[i].type,

                expand: " ",

                innerDatas:innerData               

            })                     

        }      

        console.log(dataList)

    })

const modalVisible = ref<boolean>(false);

export default defineComponent({

    components: {

        DownOutlined,

    },

    setup() {

        return {

            modal: false,

            centerDialogVisible: false,

            modalVisible,

            dataList,

            columns,

            innerColumns,

            innerData,

            cilikRow,

        };

    },

});

</script>

Guess you like

Origin blog.csdn.net/defined_/article/details/130573296