React+Ant Design使用Tree树形组件

本文介绍如何在React项目中结合Ant Design的Tree组件,实现拖拽功能,允许用户在平级节点间进行排序,并规定只能在不同父级节点间进行嵌套拖拽。

实现简单拖拽与限制树形数据平级之间不能嵌套(只能排序),不同父级之间可以拖拽嵌套.

import React, { useState, useEffect } from 'react';
import { Tree, Spin } from 'antd';
// import { EditOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import { queryDepartments, submitDepartments } from './service';
// const { Search } = Input;
// 测试数据
const { TreeNode } = Tree;

// 树形结构循环生成
const renderTree = (tree_data) => {
  if (tree_data && Array.isArray(tree_data) && tree_data.length > 0) {
    return tree_data.map((item) => {
      if (item.children && Array.isArray(item.children)) {
        return (
          <TreeNode title={item.title} key={item.key}>
            {renderTree(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode title={item.title} key={item.key} />;
    });
  }
  return [];
};

const DragTable = () => {
  const [treeData, setTreeData] = useState([]);
  const [visible, setVisible] = useState(true);
  const [expandedKeysData, setExpandedKeysData] = useState([]);

  // 获取数据,取消加载状态,设置默认展开项
  useEffect(() => {
    queryDepartments().then((res) => {
      setTreeData(res.data);
      setVisible(false);
      setExpandedKeysData(['company_9078d37085784d97a085b9738390bdc2']);
    });
  }, []);

  /* 拖拽实现 */
  const DragEnter = (expandedKeys) => {
    console.log(expandedKeys);
    // expandedKeys 需要受控时设置
    // this.setState({
    //   expandedKeys: info.expandedKeys,
    // });
  };

  // 展开/收起节点时触发
  const onExpand = (expandedKeys) => {
    setExpandedKeysData(expandedKeys);
  };

  const handleDrop = (info) => {
    // console.log(info);
    const dropKey = info.node.props.eventKey;
    const dragKey = info.dragNode.props.eventKey;
    const dropPos = info.node.props.pos.split('-');
    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
    const dropToGap = info.dropToGap;
    // console.log(dropToGap);
    // console.log(info.dropPosition);
    // console.log(dragKey);
    // console.log(dropKey);
    const str1 = dropKey.split('_');
    const str2 = dragKey.split('_');
    // console.log(str1);

    // 通过dropToGap(布尔)与每一个级别的标识,规定平级不能拖拽嵌套,不同父级可以拖拽嵌套
    if (str1[0] !== str2[0] || dropToGap) {
      const loop = (data, key, callback) => {
        for (let i = 0; i < data.length; i++) {
          if (data[i].key === key) {
            return callback(data[i], i, data);
          }
          if (data[i].children) {
            loop(data[i].children, key, callback);
          }
        }
      };

      const data = [...treeData];

      let dragObj;
      loop(data, dragKey, (item, index, arr) => {
        arr.splice(index, 1);
        dragObj = item;
      });
      if (!info.dropToGap) {
        // Drop on the content
        loop(data, dropKey, (item) => {
          item.children = item.children || [];
          // where to insert 示例添加到尾部,可以是随意位置
          item.children.push(dragObj);
        });
      } else if (
        (info.node.props.children || []).length > 0 && // Has children
        info.node.props.expanded && // Is expanded
        dropPosition === 1 // On the bottom gap
      ) {
        loop(data, dropKey, (item) => {
          item.children = item.children || [];
          // where to insert 示例添加到头部,可以是随意位置
          item.children.unshift(dragObj);
        });
      } else {
        let ar;
        let i;
        loop(data, dropKey, (item, index, arr) => {
          ar = arr;
          i = index;
        });
        if (dropPosition === -1) {
          ar.splice(i, 0, dragObj);
        } else {
          ar.splice(i + 1, 0, dragObj);
        }
      }
      // console.log(data);
      setTreeData(data);
      setTreeData(data);
      submitDepartments({
        from_key: dragKey,
        to_key: dropKey,
        drop_position: info.dropPosition,
      });
    }
    // 其他
    return;
  };

  return (
    <>
      <Spin spinning={visible}>
        <Tree
          blockNode
          checkable
          showIcon
          draggable
          expandedKeys={expandedKeysData}
          onExpand={onExpand}
          onDrop={handleDrop}
          onDragEnter={DragEnter}
        >
          {renderTree(treeData)}
        </Tree>
      </Spin>
    </>
  );
};

export default DragTable;

 

### 使用 ReactAnt Design 实现树形控件 在 React 应用程序中集成并使用 Ant Design 的 `Tree` 组件可以极大地简化开发过程。下面展示了如何安装必要的依赖项以及创建一个简单的树结构。 #### 安装依赖包 为了能够利用 Ant Design 提供的功能,首先需要通过 npm 或 yarn 来安装 antd: ```bash npm install antd --save ``` 或者如果偏好使用 yarn: ```bash yarn add antd ``` #### 导入样式文件 为了让组件正常显示,还需要导入 Ant Design 的 CSS 文件到项目中的入口 JavaScript 文件里(通常是 index.js 或 App.js): ```javascript import 'antd/dist/reset.css'; // 推荐方式,按需加载更少的样式资源 // import 'antd/dist/antd.css'; // 可选,默认全部引入 ``` #### 创建树形控件实例 接下来定义一个新的函数组件来展示一棵基本的树。这里会用到 `useState` 钩子管理状态变化,并且设置了默认展开节点和勾选项的行为逻辑。 ```jsx import React, { useState } from 'react'; import { Tree } from 'antd'; const treeData = [ { title: 'Parent Node', key: '0-0', children: [ { title: 'Child Node', key: '0-0-0' }, { title: 'Child Node', key: '0-0-1' } ] } ]; const MyTreeComponent = () => { const [checkedKeys, setCheckedKeys] = useState([]); return ( <Tree checkable onCheck={(checked) => setCheckedKeys(checked)} checkedKeys={checkedKeys} treeData={treeData} /> ); }; ``` 上述代码片段实现了带有复选框功能的基础版本树形菜单[^1]。当用户点击某个节点旁边的复选框时,该操作会被捕获并通过调用 `setCheckedKeys()` 更新当前被选中的键列表。 #### 扩展功能 对于更加复杂的场景,比如支持半选、禁用某些分支等功能,则可以通过配置更多属性来自定义行为。例如设置 `autoExpandParent=false` 让父级不会自动打开;或是传递给 `Tree` 更详细的参数对象以控制其外观与交互特性。 此外,在实际应用场景下可能还会涉及到异步加载数据的情况,这时就需要结合 API 请求和其他状态管理工具一起工作了。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值