当前位置: 首页 > news >正文

「树形结构」基于 Antd 实现一个动态增加子节点+可拖拽的树

效果

如图所示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现

import { createRoot } from 'react-dom/client';
import React, { useState } from 'react';
import { Tree, Input, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';const { TreeNode } = Tree;
const { Search } = Input;const initialData = [{title: 'Root Node',key: '0',children: [{title: ' Node',key: '1',}],},
];const DynamicTree = () => {const [treeData, setTreeData] = useState(initialData);const [expandedKeys, setExpandedKeys] = useState(['0']);const [autoExpandParent, setAutoExpandParent] = useState(true);const onExpand = (expandedKeys) => {setExpandedKeys(expandedKeys);setAutoExpandParent(false);};const addNode = (key, title = 'New Node') => {const addNodeRecursively = (nodes) => {return nodes.map((node) => {if (node.key === key) {const newNode = {title,key: `${key}-${node.children ? node.children.length : 0}`,children: [],};return {...node,children: [...node.children, newNode],};} else if (node.children) {return {...node,children: addNodeRecursively(node.children),};}return node;});};setTreeData((prevData) => addNodeRecursively(prevData));setExpandedKeys((prevKeys) => [...prevKeys, key]);};const renderTreeNodes = (data) =>data.map((item) => (<TreeNode title={item.title} key={item.key} dataRef={item}>{item.children ? renderTreeNodes(item.children) : null}<TreeNodetitle={<Buttontype="dashed"size="small"onClick={() => addNode(item.key)}icon={<PlusOutlined />}>Add Child</Button>}key={`${item.key}-add`}/></TreeNode>));return (<div><TreeshowIcononExpand={onExpand}expandedKeys={expandedKeys}autoExpandParent={autoExpandParent}>{renderTreeNodes(treeData)}</Tree></div>);
};export default DynamicTree;const ComponentDemo = DynamicTree;createRoot(mountNode).render(<ComponentDemo />);

进一步增强实现

同层级可以拖拽
增加节点的节点始终放在最后且可以增加同级节点
而且只有末级可以增加
在这里插入图片描述

import { createRoot } from 'react-dom/client';
import React, { useState } from 'react';
import { Tree, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';const { TreeNode } = Tree;const initialData = [{title: 'Root Node',key: '0',children: [],},
];const DynamicTree = () => {const [treeData, setTreeData] = useState(initialData);const [expandedKeys, setExpandedKeys] = useState(['0']);const [autoExpandParent, setAutoExpandParent] = useState(true);const onExpand = (expandedKeys) => {setExpandedKeys(expandedKeys);setAutoExpandParent(false);};const addNode = (key, title = 'New Node') => {const addNodeRecursively = (nodes) => {return nodes.map((node) => {if (node.key === key) {const newNode = {title:`${title}-${key}-${node.children ? node.children.length : 0}`,key: `${key}-${node.children ? node.children.length : 0}`,children: [],};return {...node,children: [...node.children, newNode],};} else if (node.children) {return {...node,children: addNodeRecursively(node.children),};}return node;});};setTreeData((prevData) => addNodeRecursively(prevData));setExpandedKeys((prevKeys) => [...prevKeys, key]);};const renderTreeNodes = (data, level = 0) =>data.map((item) => (<TreeNode title={item.title} key={item.key} dataRef={item}>{item.children ? renderTreeNodes(item.children, level + 1) : null}{level < 1 && (<TreeNodeselectable={false}disabled={true}icon={<PlusOutlined />}title={<Buttontype="dashed"size="small"onClick={() => addNode(item.key)}icon={<PlusOutlined />}>Add Child</Button>}key={`${item.key}-add`}/>)}</TreeNode>));const onDrop = (info) => {const dropKey = info.node.key;const dragKey = info.dragNode.key;const dropPos = info.node.pos.split('-');const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);const loop = (data, key, callback) => {data.forEach((item, index, arr) => {if (item.key === key) {return callback(item, index, arr);}if (item.children) {return loop(item.children, key, callback);}});};const data = [...treeData];let dragNode;// Find dragObjectloop(data, dragKey, (item, index, arr) => {arr.splice(index, 1);dragNode = item;});if (!info.dropToGap) {// Drop on the contentloop(data, dropKey, (item) => {item.children = item.children || [];// where to insert 示例添加到头部,可以是随意位置item.children.unshift(dragNode);});} else if ((info.node.children || []).length > 0 && // Has childreninfo.node.expanded && // Is expandeddropPosition === 1 // On the bottom gap) {loop(data, dropKey, (item) => {item.children = item.children || [];// where to insert 示例添加到头部,可以是随意位置item.children.unshift(dragNode);});} else {let ar;let i;loop(data, dropKey, (item, index, arr) => {ar = arr;i = index;});if (dropPosition === -1) {ar.splice(i, 0, dragNode);} else {ar.splice(i + 1, 0, dragNode);}}setTreeData(data);};return (<div><TreedraggableonExpand={onExpand}expandedKeys={expandedKeys}autoExpandParent={autoExpandParent}onDrop={onDrop}>{renderTreeNodes(treeData)}</Tree></div>);
};export default DynamicTree;const ComponentDemo = DynamicTree;createRoot(mountNode).render(<ComponentDemo />);

相关文章:

「树形结构」基于 Antd 实现一个动态增加子节点+可拖拽的树

效果 如图所示 实现 import { createRoot } from react-dom/client; import React, { useState } from react; import { Tree, Input, Button } from antd; import { PlusOutlined } from ant-design/icons;const { TreeNode } Tree; const { Search } Input;const ini…...

ubuntu那些ppa源在哪

Ubuntu中的 PPA 终极指南 - UBUNTU粉丝之家 什么是PPA PPA 代表个人包存档。 PPA 允许应用程序开发人员和 Linux 用户创建自己的存储库来分发软件。 使用 PPA&#xff0c;您可以轻松获取较新的软件版本或官方 Ubuntu 存储库无法提供的软件。 为什么使用PPA&#xff1f; 正如…...

20240724-然后用idea创建一个Java项目/配置maven环境/本地仓储配置

1.创建一个java项目 &#xff08;1&#xff09;点击页面的create project&#xff0c;然后next &#xff08;2&#xff09;不勾选&#xff0c;继续next &#xff08;3&#xff09;选择新项目名称&#xff0c;新项目路径&#xff0c;然后Finsh&#xff0c;在新打开的页面选择…...

PaddleOCR-PP-OCRv4推理详解及部署实现(下)

目录 前言1. 检测模型1.1 预处理1.2 后处理1.3 推理 2. 方向分类器模型2.1 预处理2.2 后处理2.3 推理 3. 识别模型3.1 预处理3.2 后处理3.3 推理 4. PP-OCRv4部署4.1 源码下载4.2 环境配置4.2.1 配置CMakeLists.txt4.2.2 配置Makefile 4.3 ONNX导出4.4 engine生成4.4.1 检测模型…...

【Golang 面试基础题】每日 5 题(二)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…...

状态模式与订单状态机的实现

状态模式 状态模式&#xff08;State Design Pattern&#xff09;是一种行为设计模式&#xff0c;用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中&#xff0c;使得对象在状态变化时不会影响到其他代码&#xff0c;提升了代码的灵活性和可维…...

【MSP430】MSP430是什么?与STM32对比哪个性能更佳?

一、MSP430是什么&#xff1f; MSP430F5529LP是一款由德州仪器&#xff08;TI&#xff09;推出的16位微控制器单元&#xff08;MCU&#xff09;开发板&#xff0c;具有USB功能&#xff0c;内存配置为128KB闪存和8KB RAM&#xff0c;工作频率高达25MHz。 这款MCU以其高性能和多…...

Win11 操作(四)g502鼠标连接电脑不亮灯无反应

罗技鼠标连接电脑不亮灯无反应 前言 罗技技术&#x1f4a9;中&#x1f4a9;&#xff0c;贴吧技术神中神&#xff01; 最近买了一个g502&#xff0c;结果买回来直接插上电脑连灯都不亮&#xff0c;问了一下客服。客服简单的让我换接口&#xff0c;又是下载ghub之类的&#xf…...

自定义QDialog使用详解

自定义QDialog使用详解 一、创建 QDialog 对象二、QDialog设置布局三、QDialog控制模态行为3.1 模态和非模态区别3.2 QDialog的模态使用四、使用 QDialogButtonBox五、处理对话框的结果六、使用 QDialog 的信号和槽QDialog是Qt框架中用于创建对话框窗口的基本类。对话框窗口通常…...

Pytorch使用教学2-Tensor的维度

在PyTorch使用的过程中&#xff0c;维度转换一定少不了。而PyTorch中有多种维度形变的方法&#xff0c;我们该在什么场景下使用什么方法呢&#xff1f; 本小节我们使用的张量如下&#xff1a; # 一维向量 t1 torch.tensor((1, 2)) # 二维向量 t2 torch.tensor([[1, 2, 3], …...

Interesting bug caused by getattr

题意&#xff1a;由 getattr 引起的有趣的 bug 问题背景&#xff1a; I try to train 8 CNN models with the same structures simultaneously. After training a model on a batch, I need to synchronize the weights of the feature extraction layers in other 7 models. …...

获取后端返回的图形验证码

如果后端返回的直接就是一个图形&#xff0c;有以下几种方式展示 一、直接在img标签里面的src里面调用接口 <img :src"dialogSrc" class"photo" alt"验证码图片" click"changeDialog">let orgUrl "/api/captcha" …...

奇怪的Excel单元格字体颜色格式

使用VBA代码修改单元格全部字符字体颜色是个很简单的任务&#xff0c;例如设置A1单元格字体颜色为红色。 Range("A1").Font.Color RGB(255, 0, 0)有时需要修改部分字符的颜色&#xff0c;如下图所示&#xff0c;将红色字符字体颜色修改为蓝色。代码将会稍许复杂&am…...

浅谈芯片验证中的仿真运行之 timescale (五)提防陷阱

一 仿真单位 timeunit 我们知道,当我们的代码中写清楚延时语句时,若不指定时间单位,则使用此单位; 例如: `timescale 1ns/1ps 则 #15 语句表示delay15ns; 例:如下代码,module a 的timescale是1ns/1ps, module b 是1ps/1ps; module b中的clk,频率是由输入参…...

uniapp 重置表单数据

场景 例如有数据如下 data(){return {queryForm:{value1:undefined,}} } 点击重置时候想重置form的数据&#xff0c; 操作 Object.assign(this.$data.queryForm, this.$options.data().queryForm); 就可以重置数据...

自学YOLO前置知识

YOLO前置知识 学习YOLO&#xff08;You Only Look Once&#xff09;之前&#xff0c;掌握一些前置知识会帮助你更好地理解和应用该技术。以下是一些推荐的前置知识领域&#xff1a; 计算机视觉基础&#xff1a; 图像处理&#xff1a;了解图像的基本处理技术&#xff0c;如滤波…...

Ubuntu18.04 编译报错: Could NOT find JNI

一、问题描述 Ubuntu18.04 编译报错 OpenCV 时&#xff0c;出现以下错误&#xff1a; Could NOT find JNI (missing: JAVA_INCLUDE_PATH JAVA_INCLUDE_PATH2 JAVA_AWT_INCLUDE_PATH)二、解决方法 先执行以下指令&#xff0c; export JAVA_HOME/usr/lib/jvm/java-8-openjdk-am…...

SQL labs-SQL注入(五,使用sqlmap进行cookie注入)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; Cookie 是一些数据, 存储于你电脑上的文本文件中。当 web 服务器向浏览器发送 web 页面时&#xff0c;在连接关闭后&#xff0c;服务端不会记录用户的信息。Cookie…...

C语言——内存管理

目录 前言 一、内存分类 1. 栈区&#xff08;Stack&#xff09; 2. 堆区&#xff08;Heap&#xff09; 3. 数据段&#xff08;Data Segment&#xff09; 4. 代码段&#xff08;Code Segment&#xff09; 二、内存分配方式 1、静态内存分配 2、栈内分配 3、动态内存分配 &#x…...

Unity UGUI 之 Image和Rawimage

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.Image是什么 Unity - 手册&#xff1a;图像 精灵格式是什么&#xff1f; 1.2重要参数 …...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...