【无标题】

本文讲述了在IT项目中构建部门树组件的经验,涉及React函数组件、ReactHooks的使用、ant.design组件库的应用、状态管理、模块化开发、异步操作处理和性能优化技巧,以及浅拷贝和深拷贝的理解。
摘要由CSDN通过智能技术生成


一、写部门树的心得

目录

一、写部门树的心得

1、学会使用React函数组件

2、  hooks应用

3、学会使用ant.design组件库组件如

4、模块化开发

总结


1、学会使用React函数组件

使用了函数组件:const DepartmentTree: React.FC = () => { ... } 表示一个 React 函数组件。

2、  hooks应用

React Hooks 是 JavaScript 函数,但在使用时需要遵循两个规则。在顶层调用hooks,在react中调用hooks,不能在循环、条件或嵌套函数中调用 Hook。

注意事项:1.更新是异步的不会立即生效,注意useState异步问题,useState更新延迟,需将操作移到适当位置。2.不要漏初始值。3.互相依赖,导致了多次渲染。4.直接更改无法更新状态,只能在set中使用函数形式修改状态。5.useState在设置状态的时候只有第一次生效,在后期更新状态是通过useEffect 来监听。6.能用其他状态计算出来就不用单独声明状态useState。7. useState的更新函数也可以接受一个函数,该函数返回新的状态值,这样可以避免依赖于先前的状态值。8.当状态是对象或数组时,更新状态应该使用展开语法确保不直接修改原对象或数组。这有助于保持不可变性。

树组件使用了状态管理的 useState 钩子:const [gData, setGData] = useState(defaultData2); 用于管理组件的状态,组件的初始值是用useState定义的。例如控制弹窗的显示与隐藏、保存树的数据等。

使用了生命周期钩子 useEffect:通过 useEffect 监听 gData 的变化,当数据变化时将其保存到 sessionStorage。

在性能要求较高的情况下,可以使用 useMemo、useCallback 等进行性能优化,避免不必要的渲染,了解高阶组件React.memo 是用于性能的优化它的作用是对于相同的 props,React.memo 可以缓存组件的渲染结果,避免不必要的渲染,从而提高组件的性能。

3、学会使用ant.design组件库组件如

Button组件:实现按钮的展示和交互。

Input:实现搜索框功能。

Form:处理表单,并通过状态管理来更新表单数据。

Modal:实现弹窗的展示,编辑和新增操作。

Tree:功能有部门树的展示、拖拽排序和交互功能、节点内容的自定义显示,实现部门树的管理展示

TreeSelect :实现树形选择功能。

Icon:学会使用icon图标如PlusOutlined、EditOutlined、CloseCircleOutlined。

PageContainer:使用 Ant Design 的 PageContainer 组件进行页面布局。

4、模块化开发

 将不同的功能拆分成多个组件,学习了父子组件之间间通信、数据、状态、函数相互传递的方法,使得代码更加模块化和可维护。父传子是通过接口参数传递,子传父是通过回调函数传递。

5、创建树形组件进行数据操作

新增删除与编辑:

  • 点击编辑按钮时,弹出一个模态框(ModelW 组件),允许用户修改部门信息。
  • 点击新增按钮时,同样弹出模态框,用户可以输入新的部门信息。
  • 删除按钮点击后会弹出确认删除的模态框,确认后执行删除操作。
  • 通过 onDragEnter 和 onDrop 处理拖拽操作,实现了节点在树中的位置调整。
  • 提供了一个搜索框,用户可以输入部门名称进行节点搜索,并在找到节点时进行展示和高亮。

6、学会处理异步操作

使用了 async/await 来处理异步操作,例如在表单验证成功后执行保存数据的操作。

7、了解持久化存储

使用 sessionStorage 将树的数据进行本地会话缓存,实现数据的持久化存储

8、学会了array的api

   1 .unshift():在数组的开头添加一个或多个元素,返回的是数组新长度

if (!info.dropToGap) {
                     loop(data, dropKey, (item) => {
                       item.children = item.children || [];
                        item.children.unshift(dragObj);
  });
} 

在部门组件的拖拽操作里 ,unshift是将dragObj添加到目标节点的子节点的开头

 使用场景:进行拖拽节点的操作,在孩子节点开头添加数据

   例如: const  变量=[ ].unshift({ })

   2 .splice():在数组中删除或添加元素,返回的是一个包含被删除元素的新数组

loop(data, dragKey, (item, index, arr) => {
                            arr.splice(index, 1);
                             dragObj = item;
                   }); 

拽节点的操作中把拖拽节点的原始数据删除,splice是找到索引为index的元素,通过splice删除 




 loop(dataTree2, node.key, (item, index, arr) => {
                          arr.splice(index, 1);
                            });  
在删除节点的操作中,splice是把从树组件中传过来的指定节点删除



 

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!);
      }
    }
    setGData(data);
  };
在拖拽节点操作中,在目标节点的子节点中找到合适的位置,插入拖拽节点

使用场景:在拖拽节点的操作中,把拖拽节点的数据从原始位置删除

                  在拖拽节点的操作中,在目标节点的子节点中找合适位置插入

                  在删除节点的操作中,把从数组件传过来的指定节点删除

例如: const arr=[ ].splice(index,1)

   3.shift():删除数组的第一个元素

  4.遍历数组的方法:

        1、for 循环:  for (let i = 0; i < array.length; i++) { 逻辑体 }

        2、forEach 方法: array.forEach((element, index, array) => { // 处理每个元素 });

        3、for...of 循环: for (const element of array) { // 处理每个元素 }

        4、map 方法:const newArray = array.map((element, index, array) => { // 返回一个新的元素 });

        5、filter 方法:const filteredArray = array.filter((element, index, array) => { // 返回 true 则保留该元素,否则过滤掉 });

        6、reduce 方法:const result = array.reduce((accumulator, element, index, array) => {
  // 使用累加器来处理数组的每个元素  }, initialValue);

5.indexOf ():用于查找数组中指定元素的索引


const findNode = (
    nodes: any[],
    targetKey: string,
    callback?: (node: any, i: number, data: any[]) => void,
  ): any | undefined => {
    for (const node of nodes) {
      if (node.key === targetKey) {
        callback?.(node, nodes.indexOf(node), nodes);
        return node;
      }
      if (node.children) {
        const foundChild = findNode(node.children, targetKey, callback);
        if (foundChild) {
          return foundChild;
        }
      }
    }
    return undefined;
  };
这是一个递归查找目标节点的方法的箭头函数,indexOf 方法用于检查 node.key 是否等于目标键 targetKey,如果等于,则执行回调函数并返回该节点。如果不等于,则递归检查子节点的 key 是否等于 targetKey。

使用场景:在嵌套的节点结构中查找指定的节点

6.some():数组的一个内建方法,用于检查数组中是否至少有一个元素满足指定的条件(即回调函数返回 true)。

function findParentNode(data: DataNode[], targetKey: string): DataNode | undefined {
  for (const node of data) {
    if (node.children) {

      if (node.children.some((child) => child.key === targetKey)) {
        return node; 
      }
some 方法用于检查 node.children 数组中是否有任意一个子节点的 key 等于目标键 targetKey。如果存在满足条件的子节点,即 some 返回 true,则 findParentNode 函数返回当前节点 node,表示找到了包含目标键的父节点。

使用场景:检查是否有等于目标节点的子节点,有则返回true,函数返回包含目标节点的父节点。用于查找上一级

7.push:作用是向数组中添加元素

二.部门树的整体构成

包含四个页面还有一个保存树结构递归方法的页面,

index:主要是树形组件的容器,写了一个父组件包含了整个部门树的逻辑和展示。负责管理树形             数据、通过useState进行更新数据,提供编辑和新增的弹窗然后通过 modifyData方法、判             断key的值确定是新增还是编辑操作,处理树节点的增删改操作,与NewTree和ModelW进              行数据的传递。

NewTree:实际的树形组件,通过 Ant Design 的 Tree 组件实现。包含树节点的渲染、拖 拽 排                       序、编辑和删除等交互逻辑。同时,也使用了 Modal 组件处理删除节点时的确认弹窗。

ModelW:弹窗组件,用于新增或编辑树节点的信息。该文件主要包含了弹窗的逻辑,通过 Ant                    Design 的 ModalForm 组件来实现。用户可以在该弹窗中输入节点的信息,然后进行                  新增或编辑操作。

FormZ:表单组件,包含了节点信息的表单,主要用于弹窗中。该组件中使用了 Ant Design 的                    FormInputTreeSelect 组件,用于展示并收集用户输入的节点信息。同时,实现了                  一些表单的验证逻辑。

treeAddEdit:

       findNodeByTitle函数作用:根据节点的标题在树形数据中查找节点,实现了不区分大小写的搜索。如果找到匹配的节点,则返回该节点;否则,返回 undefined

      modifyData函数作用:用于修改或新增树节点的数据。根据传入的参数,可以执行节点的更新或新增操作,如果传进去key表示修改操作。没有传进去key表示新增操作。

      findParentNode函数作用:在树形数据中查找给定节点的父节点,查找是否有上一级。

     findNode函数作用:在树形数据中查找指定 目标 的节点

了解深拷贝和浅拷贝的含义:

浅拷贝:多个指针栈指向一个内存堆中的地址,浅拷贝创建一个新的对象,但只复制了原对象的一层结构,而不包括嵌套的对象或数组的内部元素。浅拷贝使用的是引用复制,所以新对象中的引用和原对象中的引用指向相同的实际对象,相互影响。

深拷贝:不同的指针栈可以新增一个内存空间,相互之间不会相互影响。深拷贝创建一个新的对象,同时递归复制所有嵌套的对象和数组,使得新对象和原对象完全独立,不共享内部元素的引用。

总结

通过这次部门树组件的例子,我学会了如何创建一个部门数,以及创建部门树的流程,与其中所包含关于新增修改删除查找的逻辑,也懂得组件的拆分,在其中添加交互的功能如拖拽。但是在递归和一些需求操作细节上面还很不熟练还需要加强练习。还有在一些页面的逻辑运算也有点生疏,多练习逻辑转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值