当前位置: 首页 > 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 />);
http://www.lryc.cn/news/406155.html

相关文章:

  • ubuntu那些ppa源在哪
  • 20240724-然后用idea创建一个Java项目/配置maven环境/本地仓储配置
  • PaddleOCR-PP-OCRv4推理详解及部署实现(下)
  • 【Golang 面试基础题】每日 5 题(二)
  • 状态模式与订单状态机的实现
  • 【MSP430】MSP430是什么?与STM32对比哪个性能更佳?
  • Win11 操作(四)g502鼠标连接电脑不亮灯无反应
  • 自定义QDialog使用详解
  • Pytorch使用教学2-Tensor的维度
  • Interesting bug caused by getattr
  • 获取后端返回的图形验证码
  • 奇怪的Excel单元格字体颜色格式
  • 浅谈芯片验证中的仿真运行之 timescale (五)提防陷阱
  • uniapp 重置表单数据
  • 自学YOLO前置知识
  • Ubuntu18.04 编译报错: Could NOT find JNI
  • SQL labs-SQL注入(五,使用sqlmap进行cookie注入)
  • C语言——内存管理
  • Unity UGUI 之 Image和Rawimage
  • Lua 语法学习笔记
  • Prometheus配置alertmanager告警
  • .net core 外观者设计模式 实现,多种支付选择
  • Matlab 命令行窗口默认输出(异常)
  • LeetCode/NowCoder-二叉树OJ练习
  • PSINS工具箱函数介绍——insplot
  • Docker简单快速入门
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 图像物体的边界(200分) - 三语言AC题解(Python/Java/Cpp)
  • 【无人机】低空经济中5G RedCap芯片的技术分析报告
  • MongoDB教程(二十一):MongoDB大文件存储GridFS
  • vue 搜索框