antd树型表格的逐级展开折叠(每次展开都只展开到当前未展开的最小层级,每次折叠都只折叠到当前未折叠的最大层级)

7 篇文章 0 订阅

需求有些变态,我们用一段话和一张图来演示下

在这里插入图片描述
在这里插入图片描述
效果如下:
在这里插入图片描述

如遇到每级展开层级不一致的,如【2级2】展开到第3级,那此时点击展开,所有已展开的不动,将未展开到第3级的其他元素全部展开到第3级
在这里插入图片描述
效果如下:所有3级展开
在这里插入图片描述
折叠同理:如下,【2级2-1】收起,但当前未折叠的最大层级为【5级】
在这里插入图片描述
此时需要注意,我们应把没有子元素的【1级】,及末级均去掉,不参与折叠展开事件

效果如下:【5级】收起

在这里插入图片描述
再点击收起:【4级】收起
在这里插入图片描述
话不多说,代码直接上:

import React, { useEffect, useState, useMemo, useRef } from 'react';
import {
    Table,
    Button,
} from 'antd';
import { connect } from 'umi';
import { cloneDeep, isEqual, xorWith, isEmpty } from 'lodash';


const QualityEvaluationAccount = () => {
    // 所有已展开list
    const [expandedList, setExpandedList] = useState([])
    // 所有表格已展开key
    const [expandedKeys, setExpandedKeys] = useState([])

    const columns = [
        {
            title: 'Name',
            dataIndex: 'name',
            key: 'name',
        },
        {
            title: 'Age',
            dataIndex: 'age',
            key: 'age',
            width: '12%',
        },
        {
            title: 'Address',
            dataIndex: 'address',
            width: '30%',
            key: 'address',
        },
    ];
    const dataSource = [
        {
            key: 1,
            name: '我是一级(一)',
            age: 60,
            address: 'New York No. 1 Lake Park',
            level: 1,
            children: [
                {
                    key: 11,
                    name: '2级1',
                    age: 42,
                    address: 'New York No. 2 Lake Park',
                    level: 2,
                },
                {
                    key: 12,
                    name: '2级2',
                    age: 30,
                    address: 'New York No. 3 Lake Park',
                    level: 2,
                    children: [
                        {
                            key: 121,
                            name: '3级3-1',
                            age: 16,
                            address: 'New York No. 3 Lake Park',
                            level: 3,
                            children: [
                                {
                                    key: 1211,
                                    name: '4级4-1',
                                    age: 16,
                                    address: 'New York No. 3 Lake Park',
                                    level: 4,
                                    children: [
                                        {
                                            key: 12111,
                                            name: '5级5-1',
                                            age: 16,
                                            address: 'New York No. 3 Lake Park',
                                            level: 5,
                                        },
                                    ],
                                },
                            ],
                        },
                    ],
                },
                {
                    key: 13,
                    name: '2级3',
                    age: 72,
                    address: 'London No. 1 Lake Park',
                    level: 2,
                    children: [
                        {
                            key: 131,
                            name: '3级3-1',
                            age: 42,
                            address: 'London No. 2 Lake Park',
                            level: 3,
                            children: [
                                {
                                    key: 1311,
                                    name: '4级4-1',
                                    age: 25,
                                    address: 'London No. 3 Lake Park',
                                    level: 4,
                                },
                                {
                                    key: 1312,
                                    name: '4级4-2',
                                    age: 18,
                                    address: 'London No. 4 Lake Park',
                                    level: 4,
                                    children: [
                                        {
                                            key: 13111,
                                            name: '5级5-1',
                                            age: 23,
                                            address: 'London No. 31 Lake Park',
                                            level: 5,
                                        },
                                        {
                                            key: 13112,
                                            name: '5级5-2',
                                            age: 11,
                                            address: 'London No. 41 Lake Park',
                                            level: 5,
                                            children: [
                                                {
                                                    key: 131121,
                                                    name: '6级6-1',
                                                    age: 23,
                                                    address: 'London No. 31 Lake Park',
                                                    level: 6,
                                                },
                                                {
                                                    key: 131122,
                                                    name: '6级6-2',
                                                    age: 11,
                                                    address: 'London No. 41 Lake Park',
                                                    level: 6,
                                                },
                                            ],
                                        },
                                    ],
                                },
                            ],
                        },
                    ],
                },
            ],
        },
        {
            key: 2,
            name: '我是一级(2)',
            age: 32,
            address: 'Sydney No. 1 Lake Park',
            level: 1,
            children: [
                {
                    key: 21,
                    name: '2极2-1',
                    age: 23,
                    address: 'London No. 31 Lake Park',
                    level: 2,
                    children: [
                        {
                            key: 211,
                            name: '3极3-1',
                            age: 23,
                            address: 'London No. 31 Lake Park',
                            level: 2,
                        },
                        {
                            key: 212,
                            name: '3级3-2',
                            age: 11,
                            address: 'London No. 41 Lake Park',
                            level: 2,
                        },
                    ],
                },
                {
                    key: 22,
                    name: '2级2-2',
                    age: 11,
                    address: 'London No. 41 Lake Park',
                    level: 2,
                },
            ],
        }, {
            key: 3,
            name: '我是一级(3)',
            age: 32,
            address: 'Sydney No. 1 Lake Park',
            level: 1
        }
    ];

    // 获取树结构最大深度
    const findDeep = (obj, level = 1) => {
        let maxLev = level
        obj.children?.forEach(item => {
            if (item.children !== null) {
                const nestLevel = findDeep(item, level + 1)
                maxLev = Math.max(maxLev, nestLevel)
            }
        })
        return maxLev
    }


    const maxLevel = findDeep(dataSource[0])
    console.log('maxLevel', maxLevel)
    let arrNew = []
    const treeList = (arr) => {
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].hasOwnProperty("children")) {
                treeList(arr[i].children)
            }
            // 所有没有子集的元素均不参与展开折叠,如1级与最深层级子集
            // 因为最深层级子集无子集,所以参与展开折叠的为它的上一级
            // 第一级也不参与展开折叠
            if (!((arr[i].level === 1 || arr[i].level === maxLevel) && isEmpty(arr[i].children))) {
                arrNew.push(child(arr[i]))
            }
        }
        return arrNew;
    }

    const child = (arr) => {
        arr.children = []
        return arr;
    }

    const flatData = treeList(cloneDeep(dataSource))
    console.log('flatData', flatData)

    // 手动展开
    const open = (expanded, record, event) => {
        // console.log('expandedexpandedexpandedexpanded', expanded)
        let data = cloneDeep(expandedKeys)
        if (expanded) {
            let keys = [...data, record.key]
            setExpandedKeys(keys)
            let arr = []
            getSelectKeysData(keys, arr)
            setExpandedList(arr)
        } else {
            data.forEach((item, index) => {
                if (item === record.key) {
                    data.splice(index, 1)
                }
            })
            setExpandedKeys(data)
            let arr = []
            getSelectKeysData(data, arr)
            setExpandedList(cloneDeep(arr))
        }
    }


    // 获取已展开的key
    const getSelectKeysData = (data, arr) => {
        flatData.forEach(item => {
            data.forEach(ele => {
                if (ele === item.key) {
                    arr.push(item)
                }
            })
        })
    };


    // 展开逻辑
    // 1.先看是否全部折叠状态,如果expandedKeys为空,则展开1级

    const expand = () => {
        let level = 1
        let expandedData = cloneDeep(expandedList)
        console.log('expandedList', expandedList, expandedKeys)
        if (expandedKeys.length === 0) {
            level = 1
        } else {
            // 比较已经选择的和所有数据,筛选出未选择的条目,然后找出未展开的最小层级
            // 无需关注已展示的层级,只需要找出未选中的最小层级,去展开即可
            // 寻找两数组差集
            const unqi = xorWith(flatData, expandedData, isEqual)
            console.log('unqi', unqi)

            // 查找未展开的最小层级
            level = Math.min.apply(Math, unqi.map(function (o) { return o.level }))
            console.log('level', level)
        }

        let res = []
        console.log('flatData', flatData, level)
        flatData.forEach(item => {
            if (item.level === level) {
                // 将未展开key写入
                if (!res.includes(item.key) && !expandedKeys.includes(item.key)) {
                    res.push(item.key)
                }
            }
        })
        const keys = [...expandedKeys, ...res]
        setExpandedKeys(keys.sort((a, b) => a - b))
        let arr = []
        getSelectKeysData(cloneDeep(keys), arr)
        setExpandedList(cloneDeep(arr))
    }


    // 折叠逻辑:
    // 1.从已展开keys中找到level最大的,即为最大没有被收起的
    const shouqi = () => {

        let exList = cloneDeep(expandedList)
        let exKeys = cloneDeep(expandedKeys)

        // 只需要找出已展开的最大层级,去收起即可
        let level = Math.max.apply(Math, exList.map(function (o) { return o.level }))

        console.log('shouqi- level', level)
        let keyList = []
        exList.forEach((item, index) => {
            if (item.level === level) {
                keyList.push(item.key) // 找出要删除的key
            }
        })
        console.log('exList', exList, keyList)

        // 在已展开keys中删除key
        // 取已展开列表和删除列表的两数组差集
        const unqi = xorWith(exKeys, keyList, isEqual)
        console.log('unqi', unqi)
        setExpandedKeys(unqi)
        let arr = []
        getSelectKeysData(unqi, arr)
        console.log('arr-====', arr)
        setExpandedList(cloneDeep(arr))
    }


    return (
        <>
            <Button onClick={expand}>展开</Button>
            <Button onClick={shouqi}>折叠</Button>

            <Table
                columns={columns}
                dataSource={dataSource}
                rowKey={record => record.key}
                expandedRowKeys={expandedKeys}
                onExpand={(record, event) => open(record, event)}
            />
        </>
    );
}

export default QualityEvaluationAccount;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值