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

news2024/11/16 1:33:31

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

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

如遇到每级展开层级不一致的,如【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;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1074449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

东土科技与诺贝尔物理学奖2006年度得主斯穆特签约,加快布局工业AI

近日&#xff0c;诺贝尔物理学奖2006年度得主乔治.斯穆特教授与东土科技正式签约&#xff0c;成为东土科技工业人工智能顾问。 乔治斯穆特&#xff08;George Fitzgerald Smoot&#xff09;教授也曾获得爱因斯坦奖&#xff0c;在宇宙学、大数据、生物医学诊断仪器以及人工智能…

第一章:随机过程预备知识

第一章&#xff1a;随机过程预备知识 随机过程属于概率论的分支学科。概率论注重结果&#xff1a;上涨的概率&#xff0c;下跌的概率。随机过程注重过程&#xff0c;随着时间的推移&#xff0c;结果的演化过程。 1.1 随机事件与概率的定义 事件的本质是集合&#xff0c;有关集…

workerman的基本用法(示例详解)

workerman是什么&#xff1f; Workerman是一个异步事件驱动的PHP框架&#xff0c;具有高性能&#xff0c;可轻松构建快速&#xff0c;可扩展的网络应用程序。支持HTTP&#xff0c;Websocket&#xff0c;SSL和其他自定义协议。支持libevent&#xff0c;HHVM&#xff0c;ReactPH…

朋友一口气拿下字节27K的offer,实名羡慕了....

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

DRM全解析 —— framebuffer详解(1)

本文参考以下博文&#xff1a; Linux内核4.14版本——drm框架分析(1)——drm简介 特此致谢&#xff01; 1. 简介 framebuffer是一块内存区域&#xff0c;可以理解为一块画布&#xff0c;驱动和应用层都能访问它。绘制前需要将它格式化&#xff0c;设定绘制的色彩模式&#x…

leetcode:217. 存在重复元素(python3解法)

难度&#xff1a;简单 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &#xff0c;返回 true &#xff1b;如果数组中每个元素互不相同&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1] 输出&#xff1a;true 示例 2&#xff1a; 输…

DruidDataSource导致OOM问题处理

DruidDataSource导致OOM问题处理 起因分析日志分析Dump文件问题分析处理 起因 一个平凡的工作日&#xff0c;我像往常一样完成产品提出的需求的业务代码&#xff0c;突然收到了监控平台发出的告警信息。本以为又是一些业务上的 bug 导致的报错&#xff0c;一看报错发现日志写着…

Deepwalk,Node2vec算法原理生动理解(图文)

Deepwalk算法原理详解 DeepWalk算法之所以能够有效地学习节点的低维表示&#xff0c;是因为它利用了本质上与自然语言处理相同的思路&#xff1a;图是一种高维数据&#xff0c;很难直接处理&#xff0c;但是可以将其映射到低维空间中&#xff0c;这样可以更好地进行处理 Deep…

ElasticSearch 使用 searchAfter() 进行遍历查询 查到的数据总数小于 totalHits

ElasticSearch 使用 searchAfter() 进行遍历查询&#xff0c;查到的数据总数小于 totalHits&#xff0c;并且每次查询的页 size 越大&#xff0c;遍历总数和 totalHits 的差距越小。 原因 这是由于如下的机制&#xff1a; 每个文档具有一个唯一值的字段应该用作排序规范的仲裁…

2023 IDC中国数字金融论坛丨中电金信向行业分享“源启+应用重构”新范式

9月8日&#xff0c;IDC主办的“2023 IDC中国数字金融论坛”在北京召开。中电金信受邀参会&#xff0c;并带来了深度数字化转型趋势之下关于应用重构的分享与洞见。 论坛重点关注金融科技创新发展趋势与数字化转型之路&#xff0c;中电金信副总经理、研究院院长况文川带来了“创…

多无人机编队集群飞行

matlab2016b可直接运行 多无人机集群编队飞行&#xff08;8架无人机&#xff09;资源-CSDN文库

S7-1200PLC与力控通过S7协议进行通信的具体步骤示例

S7-1200PLC与力控通过S7协议进行通信的具体步骤示例 准备条件: TIA PORTAL V16 力控7.2 SP3 PLC:1214 DC/DC/DC PLC一侧的配置: PLC IP设置为192.168.2.10 PLC属性中的连接机制,勾选允许来自远程对象的PUT/GET 新建一个名为FirstDB的数据块,数据块编号为1 在FirstDB中添加…

大屏设计器项目部署详细步骤

一.项目效果图 二.部署步骤 1.nginx配置前端配置 #gzip on;server {listen 48009;server_name analyse;location / {root /home/designer/dist;index index.html;try_files $uri

vue中v-model的原理是什么?v-model作用在组件上的原理是什么?sync修饰符的原理是什么?

vue中v-model的原理是什么&#xff1f; 特点&#xff1a;双向绑定 数据>视图 视图>数据 场景&#xff1a; 收集表单数据组件上 原理&#xff1a; v-model只是个语法题&#xff0c;本质是&#xff1a;v-model v-bind (:value) v-on (input) <template><…

蓝牙资讯|三星推迟发布智能戒指Galaxy Ring,智能穿戴小型化是大趋势

根据外媒 The Elec 报道&#xff0c;Galaxy Ring这款戒指主要面向健康和 XR 头显市场&#xff0c;该智能戒指可能被延期至 2024 年第三季度后发布。 外媒声称三星 Galaxy Ring 的上市周期&#xff0c;主要取决医疗认证的相关审批时间&#xff0c;三星计划将在 2024 年第三季度…

2023年软件测试工具总结 —— 性能测试工具

软件性能测试的目标是识别应用程序中的所有性能瓶颈。一个软件系统的性能不仅取决于系统本身的设计和编码&#xff0c;而且取决于系统所依赖的运行环境。系统的运行环境会依赖于一些关键因素&#xff0c;例如&#xff1a;系统架构、硬件配置、网络带宽、配套的软件如数据库和中…

java多线程卖电影票的三种实现方式

java多线程卖电影票的三种实现方式 一、需求描述二、实现方式1、继承Thread类的方式2、实现Runnable接口的方式3、使用Lock锁的方式 一、需求描述 某电影院目前正在上映国产大片&#xff0c;共有1000张票&#xff0c;而它有2个窗口卖票&#xff0c;请设计一个程序模拟该电影院…

12.3 实现模拟鼠标录制回放

本节将向读者介绍如何使用键盘鼠标操控模拟技术&#xff0c;键盘鼠标操控模拟技术是一种非常实用的技术&#xff0c;可以自动化执行一些重复性的任务&#xff0c;提高工作效率&#xff0c;在Windows系统下&#xff0c;通过使用各种键盘鼠标控制函数实现动态捕捉和模拟特定功能的…

Ubuntu22.04.3安装教程

虚拟机系列文章 VMware Workstation Player 17 免费下载安装教程 VMware Workstation 17 Pro 免费下载安装教程 windows server 2012安装教程 Ubuntu22.04.3安装教程 FTP服务器搭建 Ubuntu22.04.3安装教程 虚拟机系列文章前言Ubuntu22.04.3安装&#xff08;图文&#xff09; 前…

【C++心愿便利店】No.7---C++之运算符重载

文章目录 前言一、运算符重载的引用二、运算符重载三、赋值运算符重载四、日期类的实现五、const成员六、取地址及const取地址操作符重载 前言 &#x1f467;个人主页&#xff1a;小沈YO. &#x1f61a;小编介绍&#xff1a;欢迎来到我的乱七八糟小星球&#x1f31d; &#x1f…