实现Ant Design Tree组件的节点的增删改

实现Ant Design Tree组件的节点的增删改

在做项目时最近遇到一个需求,需要用到Antd中的tree,并能够实现对tree的节点的增加和删除,以及节点名称的修改。去翻Antd官网文档,发现tree组件并没有提供关于节点操作的api,但是有鼠标右击的api。借助这个鼠标右击,以及其他组件是可以实现对节点的增删改。下面进行截图介绍:

截图介绍

第一部分:Tree组件

  1. 最外层节点只能增加子节点
    请添加图片描述
  2. 父节点可以增加子节点,修改自己的节点名称,删除节点
    请添加图片描述

3.最内层节点不允许再添加子节点,只允许修改自己的节点名称和删除该节点
请添加图片描述

第二部分:Tooltip组件

4.点击添加子节点。这里用到了Tooltip组件,包装成button,设置点击事件弹出Model框输入节点名称以添加
请添加图片描述
5.修改节点
请添加图片描述
6.删除节点请添加图片描述

第三部分:Model组件

实现弹出窗交互

具体代码

话不多说,直接上代码,能力有限,仅供参考。

import React, { Component } from 'react'
import {Tree,Tooltip,Modal,Form,Input,message} from 'antd';
import {PlusCircleOutlined,EditOutlined,MinusCircleOutlined}from '@ant-design/icons';
import { reqGetTreeNode,reqAddTreeNode,reqUpdateTreeNode,reqDeleteTreeNode,reqGetPageInfo} from '../../api';
const { DirectoryTree } = Tree;
export default class TreeNode extends Component {
    formRef = React.createRef();
    state={
          role:0,
          treeData:[],
          defaultExpandedKeys:'',
          NodeTreeItem: null, //右键菜单
          visible: false,     
          isModalVisible:false,//是否显示modal 新建组织或者修改组织
          isHideAdd:'',      //是否展示添加按钮
          isHideUpdate:'',   //是否展示修改按钮
          isHideDelete:'',  //是否展示删除按钮
          operType:'',      //区别Modal弹出框的类型,(添加,修改,删除用的是一个Modal)
          text:'',
          isLoading:true
    }
    getTreeNode = async() => {
        const result = await reqGetTreeNode();
        this.addIsLeaf(result.value)
        this.setState({treeData:[{
            title: '信息管理',
            key: '1',
            children: [...result.value],
      }], 
      defaultExpandedKeys:result.value[0].key,
      isLoading:false
     })
    }
    addIsLeaf = (treenode) =>{
      treenode.forEach((item)=>{
        if(item.children.length === 0 ){
          item.isLeaf =true
        }else{
          this.addIsLeaf(item.children)
        }
      })
    }
    componentDidMount(){
        this.getTreeNode();
    }

    onSelect =async (keys,info) =>{
      this.setState({NodeTreeItem:null});
      const {key,pos} = info.node;
      //这里写点击tree节点的事件逻辑
    }

    //右键点击事件(注意,这里的右键的Tooltip位置不是很精确,需要微调)
    onRightClick = ({event,node}) => {
      var x = -75;                
      var y = event.clientY - 112 ;
      const pos = node.pos.split('-').length - 1; 
      if(pos === 1){
        this.setState({
          NodeTreeItem: {
            pageX: x,
            pageY: y,
            key: node.key,
            name: node.title,
            pos:pos
          },
          isHideUpdate:'none',
          isHideDelete:'none'
        });
      }else if(pos === 3){
        this.setState({
          NodeTreeItem: {
            pageX: x,
            pageY: y,
            key: node.key,
            name: node.title,
            pos:pos
          },
          isHideAdd:'none'
        });
      }else{
        this.setState({
          NodeTreeItem: {
            pageX: x,
            pageY: y,
            key: node.key,
            name: node.title,
            pos:pos
          },
          isHideAdd:'',
          isHideUpdate:'',
          isHideDelete:''
        });
      }
    }
    //增删改组件
    getNodeTreeMenu() {
      const {pageX, pageY} = {...this.state.NodeTreeItem};
      const tmpStyle = {
        position: 'absolute',
        maxHeight: 40,
        textAlign: 'center',
        left: `${pageX}px`,
        top: `${pageY}px`,
        display: 'flex',
        flexDirection: 'row',
      };
      const menu = (
        <div
          style={tmpStyle}
        >
          <div style={{alignSelf: 'center', marginLeft: 10,display:this.state.isHideAdd}} onClick={this.handleAddSub}>
            <Tooltip placement="bottom" title="添加子节点" >
            <PlusCircleOutlined />
            </Tooltip>
          </div>
          <div style={{alignSelf: 'center', marginLeft: 10,display:this.state.isHideUpdate}} onClick={this.handleEditSub}>
            <Tooltip placement="bottom" title="修改节点">
            <EditOutlined />
            </Tooltip>
          </div>
          {this.state.NodeTreeItem.category === 1?'':(
            <div style={{alignSelf: 'center', marginLeft: 10,display:this.state.isHideDelete}} onClick={this.handleDeleteSub}>
            <Tooltip placement="bottom" title="删除该节点">
            <MinusCircleOutlined />
            </Tooltip>
          </div>
          )}
        </div>
      );
      return (this.state.NodeTreeItem == null) ? '' : this.state.role ===
      0 ? menu : '';
    }

    //添加按钮弹出添加Modal
    handleAddSub = () =>{
      this.setState({isModalVisible:true,operType:'add'})
    }
    //修改按钮弹出修改Modal
    handleEditSub = () => {
      const {NodeTreeItem} = this.state;
      this.setState({isModalVisible:true,operType:'update'})
      this.formRef.current.setFieldsValue({name:NodeTreeItem.name});
    }
    //删除按钮弹出删除Modal
    handleDeleteSub = () => {
      this.setState({isModalVisible:true,operType:'delete'})
    }

    //节点添加方法
    toAdd = async (values) => {
        const {NodeTreeItem} = this.state;
        const result = await reqAddTreeNode(values.name,NodeTreeItem.key);
        if(result.msg === 'success'){
          message.success('节点添加成功')
        }else{
          message.error('节点添加失败,请重试')
        }
        this.setState({isModalVisible:false})
        this.getTreeNode();
    }

    //节点更新方法
    toUpdate = async (values) => {
      const {NodeTreeItem} = this.state;
      const result = await reqUpdateTreeNode(NodeTreeItem.key,values.name,NodeTreeItem.pos);
      if(result.msg === 'success'){
        message.success('节点修改成功')
      }else{
        message.error('节点修改失败,请重试')
      }
      this.setState({isModalVisible:false})
      this.getTreeNode();
    }

    //节点删除方法
    toDelete = async () => {
      const {NodeTreeItem} = this.state;
      const result = await reqDeleteTreeNode(NodeTreeItem.key,NodeTreeItem.pos);
      if(result.msg === 'success'){
        message.success('节点删除成功')
      }else{
        message.error('节点删除失败,请重试')
      }
      this.setState({isModalVisible:false,NodeTreeItem:null})
      this.getTreeNode();
    }

    //Modal确定的回调
    handleOk = () => {
          const {operType} = this.state;
          this.formRef.current.validateFields().then(values=>{
            if(operType==='add'){
              this.toAdd(values);
            }else if(operType==='update'){
              this.toUpdate(values);
            }else{
              this.toDelete();
            }
      }).catch(reason=>{
        message.warning('表单输入不允许为空,请检查');
      })
    }


    //Modal取消的回调
    handleCancel=(e)=>{
      this.formRef.current.resetFields();
      this.setState(()=>{
        return({isModalVisible:false})
      });
    }

    
    render() {
      const {isModalVisible,operType,treeData,isLoading,defaultExpandedKeys} = this.state;
      if(isLoading == true){
          return null
      }else{
          return (
            <>
            <div style={{display: 'flex',marginRight:'20px'}}>
              <DirectoryTree
              multiple
              defaultExpandAll
              // defaultExpandedKeys={}
              onSelect={this.onSelect}
              treeData={treeData}
              onRightClick={this.onRightClick}
              style={{width:'250px'}}
              />
                <div style={{position:'relative',}}>
              {this.state.NodeTreeItem != null ? this.getNodeTreeMenu() : ""}
              </div>
            </div>
            
              
              <Modal 
                title={operType === 'add' ? '添加节点' : operType === 'delete' ? '删除节点' : '修改节点'} 
                visible={isModalVisible} 
                onOk={this.handleOk} 
                okText="确定"
                onCancel={this.handleCancel}
                cancelText="取消"
                forceRender={true}
                >
                  {operType === 'add' ? '请输入要添加节点的名称' : operType === 'delete' ? '您确定要删除该节点吗?' : '请输入要修改节点的名称'}
                    <Form
                    name="normal"
                    ref={this.formRef}
                    style={{display:operType === 'delete' ? 'none' : ''}}
                    >
                      <Form.Item
                      name="name"
                      rules={[
                      {required: operType === 'delete'? false : true,message: '节点名称不允许为空'},
                      ]}
                      >
                          <Input placeholder="请输入节点名称" />
                      </Form.Item>
                    </Form>
                </Modal>
            </>
        )
      }
        
    }
}

乾坤未定,你我皆是黑马!

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
您好!要使Ant Design Tree树形组件的叶子节点横向排列,您可以使用Tree组件treeNode属性来自定义节点的渲染方式。以下是一种实现方式: 首先,您需要引入Tree组件和Icon组件: ```jsx import { Tree, Icon } from 'antd'; ``` 然后,您可以通过自定义渲染函数来调整叶子节点的布局。在渲染函数中,您可以根据节点的isLeaf属性来判断是否为叶子节点,如果是叶子节点,则将其横向排列。以下是一个示例: ```jsx const renderTreeNodes = (data) => { return data.map((item) => { if (item.children) { return ( <Tree.TreeNode title={item.title} key={item.key}> {renderTreeNodes(item.children)} </Tree.TreeNode> ); } return ( <Tree.TreeNode title={item.title} key={item.key} isLeaf> {item.title} </Tree.TreeNode> ); }); }; ``` 在上面的示例中,我们通过设置isLeaf属性为true来标识叶子节点,并在叶子节点的title属性中添加了一个自定义的布局。 最后,您可以将渲染函数应用到Tree组件中,并将数据传递给Tree组件treeData属性: ```jsx const treeData = [ { title: 'Node 1', key: '0-0', children: [ { title: 'Leaf 1', key: '0-0-0', }, { title: 'Leaf 2', key: '0-0-1', }, ], }, { title: 'Node 2', key: '0-1', children: [ { title: 'Leaf 3', key: '0-1-0', }, { title: 'Leaf 4', key: '0-1-1', }, ], }, ]; const MyTree = () => { return ( <Tree showLine> {renderTreeNodes(treeData)} </Tree> ); }; ``` 在上面的示例中,我们使用了一个简单的树形数据结构,并将其传递给了Tree组件treeData属性。通过调用renderTreeNodes函数,我们实现了叶子节点横向排列的效果。 希望这可以帮助到您!如果您还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.ToString()°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值