>웹 프론트엔드 >프런트엔드 Q&A >반응으로 트리에 노드를 추가하는 방법

반응으로 트리에 노드를 추가하는 방법

藏色散人
藏色散人원래의
2023-01-18 14:09:141554검색

React에서 트리에 노드를 추가하는 방법: 1. antd의 트리 제어를 도입하고 "const treeData = [...]"를 통해 트리 모양 구성 요소를 구현합니다. 2. 현재 노드의 키 값을 전달한 다음 데이터 배열; 3. 노드를 추가하기 위해 배열을 탐색할 때 중첩된 배열 개체의 쿼리 알고리즘을 통해 노드를 추가하면 됩니다.

반응으로 트리에 노드를 추가하는 방법

이 튜토리얼의 운영 환경: Windows 10 시스템, 반응 버전 18.0.0, Dell G3 컴퓨터.

반응에서 트리에 노드를 추가하는 방법은 무엇입니까?

React 프로젝트는 노드 추가, 삭제 및 수정을 구현하기 위해 antd의 트리 제어를 도입합니다.

머리말

일부 주요 인터뷰 질문을 검색할 때 일부 인터뷰 질문에서는 다음을 수행해야 한다는 것을 알았습니다. antd를 기반으로 답변 작성 원래 antd 구성 요소는 트리 컨트롤을 추가, 삭제, 수정하는 것이 매우 간단해야 한다고 생각했지만, 시작했을 때 여전히 많은 노력이 필요할 것이라고는 예상하지 못했습니다. 그래서 요구사항을 실현하는 전 과정을 기록할 예정이다.

1. antd의 트리 컨트롤 소개

antd를 사용해 본 친구들은 antd를 사용한다는 것은 코드 예제를 붙여넣은 다음 자신의 필요와 antd에서 제공하는 API에 맞게 변경하는 것임을 알아야 합니다. 그래서 여기서는 간단한 antd 트리 제어 코드 예제도 찾고 있습니다. 무슨 일이 있어도 먼저 붙여넣고 결과가 무엇인지 확인하세요.

import React from "react";
import { Tree } from "antd";const treeData = [
  {
    title: "0-0",
    key: "0-0",
    children: [
      {
        title: "0-0-0",
        key: "0-0-0",
        children: [
          { title: "0-0-0-0", key: "0-0-0-0" },
          { title: "0-0-0-1", key: "0-0-0-1" },
          { title: "0-0-0-2", key: "0-0-0-2" },
        ],
      },
      {
        title: "0-0-1",
        key: "0-0-1",
        children: [
          { title: "0-0-1-0", key: "0-0-1-0" },
          { title: "0-0-1-1", key: "0-0-1-1" },
          { title: "0-0-1-2", key: "0-0-1-2" },
        ],
      },
      {
        title: "0-0-2",
        key: "0-0-2",
      },
    ],
  },
  {
    title: "0-1",
    key: "0-1",
    children: [
      { title: "0-1-0-0", key: "0-1-0-0" },
      { title: "0-1-0-1", key: "0-1-0-1" },
      { title: "0-1-0-2", key: "0-1-0-2" },
    ],
  },
  {
    title: "0-2",
    key: "0-2",
  },];export default function TreeDemo() {
  return (
    <div>
      <tree></tree>
    </div>
  );}

여기에는 간단한 트리 형태의 컴포넌트가 구현되어 있는데, 이 컴포넌트는 기본적으로 브라우징 외에는 기능이 없으므로 재구성이 필요합니다.
반응으로 트리에 노드를 추가하는 방법

2. 컴포넌트 코드 구조 변환

일반적으로 antd 컴포넌트를 사용할 때 가장 중요한 것은 antd에서 제공하는 API를 사용하는 것입니다. 작성 방법은 모르지만 꽤 쉬울 것입니다. 우리가 그것을 사용할 수 있다면. 트리 컨트롤의 API를 탐색할 때 <tree></tree> 구성 요소에 가장 작은 하위 구성 요소인 <treenode></treenode>가 있는 것을 발견했습니다. 전체 트리 제어 장치를 구성하는 구성 요소입니다. 따라서 추가, 삭제 및 수정을 구현하려면 이 <treenode></treenode> 구성 요소에 대해 열심히 노력해야 합니다. 이 아이디어를 바탕으로 다음과 같이 변형됩니다. <tree></tree>组件有个子组件<treenode></treenode>,它就是组成整个树形控件的最小单元。所以我们如果要实现增删改的话,就要在这个<treenode></treenode>组件上下功夫。根据这个思路然后改造成如下的样子。

import React, { useState } from "react";import { Tree } from "antd";const { TreeNode } = Tree;const treeData = [
  {
    value: "0",
    key: "0",
    children: [
      {
        value: "0-1",
        key: "0-1",
      },
      {
        value: "0-2",
        key: "0-2",
      },
    ],
  },];export default function TreeDemo() {
  const [data, setdata] = useState(treeData);
  const renderTreeNodes = (data) => {
    let nodeArr = data.map((item) => {
      item.title = <span>{item.value}</span>;

      if (item.children) {
        return (
          <treenode>
            {renderTreeNodes(item.children)}
          </treenode>
        );
      }

      return <treenode></treenode>;
    });

    return nodeArr;
  };

  return (
    <div>
      <tree>{renderTreeNodes(data)}</tree>
    </div>
  );}

然后就是如下的样子:
반응으로 트리에 노드를 추가하는 방법
这里要说明的一点是<treenode></treenode>

import React, { useState } from "react";import { Tree } from "antd";import {
    EditOutlined,
    PlusOutlined,
    MinusOutlined,
  } from "@ant-design/icons";const { TreeNode } = Tree;const treeData = [
  {
    value: "0",
    key: "0",
    children: [
      {
        value: "0-1",
        key: "0-1",
      },
      {
        value: "0-2",
        key: "0-2",
      },
    ],
  },];export default function TreeDemo() {
  const [data, setdata] = useState(treeData);
  const renderTreeNodes = (data) => {
    let nodeArr = data.map((item) => {
      item.title = (
        <div>
          <span>{item.value}</span>
          <span>
            <editoutlined></editoutlined>

            <plusoutlined></plusoutlined>
           
            <minusoutlined></minusoutlined>
          </span>
        </div>
      );

      if (item.children) {
        return (
          <treenode>
            {renderTreeNodes(item.children)}
          </treenode>
        );
      }

      return <treenode></treenode>;
    });

    return nodeArr;
  };

  return (
    <div>
      <tree>{renderTreeNodes(data)}</tree>
    </div>
  );}
그러면 다음과 같습니다:


여기서 주목할 점은 <treenode></treenode>의 제목이 ReactNode 유형의 데이터를 받기 때문에 이를 기반으로 아이콘 클래스를 추가하는 등 데이터를 표시하는 스타일을 정의할 수 있다는 점입니다. 그러면 이 시점에서 요구사항에 추가, 삭제 및 수정 기능이 있어야 한다는 것을 모두가 알아야 하며, 이 제목을 사용하여 이를 보여주고 코드를 변환할 수 있습니다. 반응으로 트리에 노드를 추가하는 방법

import React, { useState } from "react";import { Tree } from "antd";import { EditOutlined, PlusOutlined, MinusOutlined } from "@ant-design/icons";const { TreeNode } = Tree;const treeData = [
  {
    value: "0",
    key: "0",
    children: [
      {
        value: "0-1",
        key: "0-1",
      },
      {
        value: "0-2",
        key: "0-2",
      },
    ],
  },];export default function TreeDemo() {
  const [data, setdata] = useState(treeData);

  const renderTreeNodes = (data) => {
    let nodeArr = data.map((item) => {
      item.title = (
        <div>
          <span>{item.value}</span>
          <span>
            <editoutlined></editoutlined>

            <plusoutlined>onAdd(item.key)} />

            <minusoutlined></minusoutlined>
          </plusoutlined></span>
        </div>
      );

      if (item.children) {
        return (
          <treenode>
            {renderTreeNodes(item.children)}
          </treenode>
        );
      }

      return <treenode></treenode>;
    });

    return nodeArr;
  };

  const onAdd = (key) => {
    addNode(key,treeData); 
    //useState里数据务必为immutable (不可赋值的对象),所以必须加上slice()返回一个新的数组对象
    setdata(treeData.slice())
  };

  const addNode = (key,data) =>
    data.forEach((item) => {
      if (item.key === key) {
        if (item.children) {
          item.children.push({
            value: "default",
            key: key + Math.random(100), // 这个 key 应该是唯一的
          });
        } else {
          item.children = [];
          item.children.push({
            value: "default",
            key: key + Math.random(100),
          });
        }
        return;
      }
      if (item.children) {
       addNode(key, item.children);
      }
    });

  return (
    <div>
      <tree>{renderTreeNodes(data)}</tree>
    </div>
  );}

이제 버튼이 3개가 있는데 아직 특정 기능을 사용할 수 없으니 하나씩 해보죠.


3. 노드 추가 기능 구현

노드를 추가하려면 구현 방법은 현재 노드의 키 값을 전달한 후 데이터 배열을 순회하여 노드를 추가하는 것입니다. 지난 2주 동안 배운 배열의 깊이 우선 및 너비 우선 순회 아이디어를 사용하는 중첩 배열 객체의 쿼리 알고리즘.
다음은 이 아이디어를 바탕으로 수정된 코드입니다. 반응으로 트리에 노드를 추가하는 방법

  const onEdit = (key) => {
    editNode(key, treeData);
    setData(treeData.slice())
  };

  const editNode = (key, data) =>
    data.forEach((item) => {
      if (item.key === key) {
        item.isEditable = true;
      } else {
        item.isEditable = false;
      }
      item.value = item.defaultValue; // 当某节点处于编辑状态,并改变数据,点击编辑其他节点时,此节点变成不可编辑状态,value 需要回退到 defaultvalue
      if (item.children) {
        editNode(key, item.children);
      }
    });const treeData = [
  {
    value: "0",
    key: "0",
    isEditable: false,
    children: [
      {
        value: "0-1",
        key: "0-1",
        isEditable: false,
      },
      {
        value: "0-2",
        key: "0-2",
        isEditable: false,
      },
    ],
  },];
추가 버튼을 클릭하면 새로운 기본 노드가 나타납니다.

3. 노드 편집 기능을 구현합니다.

추가 아이디어를 얻은 후 위의 노드 이후의 편집은 삭제 기능을 사용하는 것이 더 쉽습니다. 여기에는 코드 조각만 표시되어 있으며 코드의 최종 버전은 기사 끝에 있습니다. 노드를 편집할 때 노드를 편집 가능하게 만들어야 하므로 변수를 사용하여 관리해야 합니다.
 const onDelete = (key) => {
    deleteNode(key, treeData);
    setData(treeData.slice());
  };

  const deleteNode = (key, data) =>
    data.forEach((item, index) => {
      if (item.key === key) {
        data.splice(index, 1);
        return;
      } else {
        if (item.children) {
          deleteNode(key, item.children);
        }
      }
    });

4. 노드 삭제 기능 구현
import React, { useState} from "react";import { Tree } from "antd";import {
  EditOutlined,
  PlusOutlined,
  MinusOutlined,
  CloseOutlined,
  CheckOutlined,} from "@ant-design/icons";import {nanoid} from "nanoid";const { TreeNode } = Tree;const treeData = [
  {
    value: "0",
    defaultValue: "0",
    key: "0",
    parentKey: '0',
    isEditable: false,
    children: [
      {
        value: "0-1",
        key: "0-1",
        defaultValue: "0-1",
        isEditable: false,
      },
      {
        value: "0-2",
        key: "0-2",
        defaultValue: "0-2",
        isEditable: false,
      },
    ],
  },];const expandedKeyArr = ["0"];export default function TreeDemo() {
  const [data, setData] = useState(treeData);
  const [expandedKeys, setExpandedKeys] = useState(expandedKeyArr);

  const onExpand = (expandedKeys) => {
    //记录折叠的key值
    setExpandedKeys(expandedKeys);
  };
  const renderTreeNodes = (data) => {
    let nodeArr = data.map((item) => {
      if (item.isEditable) {
        item.title = (
          
             onChange(e, item.key)} />              onClose(item.key, item.defaultValue)}             />              onSave(item.key)}             />           
        );       } else {         item.title = (           
            {item.value}                             onEdit(item.key)}               />                onAdd(item.key)}               />               {item.parentKey === "0" ? null : (                  onDelete(item.key)}                 />               )}                        
        );       }       if (item.children) {         return (                        {renderTreeNodes(item.children)}                    );       }       return <treenode></treenode>;     });     return nodeArr;   };   const onAdd = (key) => {     if (expandedKeys.indexOf(key) === -1) {       expandedKeyArr.push(key);     }     setExpandedKeys(expandedKeyArr.slice());     addNode(key, treeData);     //useState里数据务必为immutable (不可赋值的对象),所以必须加上slice()返回一个新的数组对象     setData(treeData.slice());   };   const onEdit = (key) => {     editNode(key, treeData);     setData(treeData.slice());   };   const editNode = (key, data) =>     data.forEach((item) => {       if (item.key === key) {         item.isEditable = true;       } else {         item.isEditable = false;       }       item.value = item.defaultValue; // 当某节点处于编辑状态,并改变数据,点击编辑其他节点时,此节点变成不可编辑状态,value 需要回退到 defaultvalue       if (item.children) {         editNode(key, item.children);       }     });   const addNode = (key, data) =>     data.forEach((item) => {       if (item.key === key) {         if (item.children) {           item.children.push({             value: "default",             key: nanoid(), // 这个 key 应该是唯一的           });         } else {           item.children = [];           item.children.push({             value: "default",             key: nanoid(),           });         }         return;       }       if (item.children) {         addNode(key, item.children);       }     });   const onChange = (e, key) => {     changeNode(key, e.target.value, treeData);     setData(treeData.slice());   };   const changeNode = (key, value, data) =>     data.forEach((item) => {       if (item.key === key) {         item.value = value;       }       if (item.children) {         changeNode(key, value, item.children);       }     });   const onSave = (key) => {     saveNode(key, treeData);     setData(treeData.slice());   };   const saveNode = (key, data) =>     data.forEach((item) => {       if (item.key === key) {         item.defaultValue = item.value;       }       if (item.children) {         saveNode(key, item.children);       }       item.isEditable = false;     });   const onClose = (key, defaultValue) => {     closeNode(key, defaultValue, treeData);     setData(treeData);   };   const closeNode = (key, defaultValue, data) =>     data.forEach((item) => {       item.isEditable = false;       if (item.key === key) {         item.value = defaultValue;       }       if (item.children) {         closeNode(key, defaultValue, item.children);       }     });   const onDelete = (key) => {     deleteNode(key, treeData);     setData(treeData.slice());   };   const deleteNode = (key, data) =>     data.forEach((item, index) => {       if (item.key === key) {         data.splice(index, 1);         return;       } else {         if (item.children) {           deleteNode(key, item.children);         }       }     });   return (     
               {renderTreeNodes(data)}            
  );}
5. 전체 코드
rrreee는 학습을 권장합니다: "🎜react video tutorial🎜"🎜

위 내용은 반응으로 트리에 노드를 추가하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.