我有一个用对象数组递归绘制的树.我能够调出具有所有展开折叠相关功能的树.现在,我想使用输入元素在树中进行搜索.这种搜索应该以递归方式进行.当叶 node 匹配时,树应该显示直到该叶 node 的所有 node .正在扩张.当中间 node 或根 node 匹配时,它应该只显示到该级别,并显示折叠的图标,然后可以展开该图标.

到目前为止,这就是我try 过的.

node 组件

import React, { useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

export const Node = ({ node, level, currentActive, setCurrentActive }) => {
  const [isOpen, setIsOpen] = useState(false);
  const hasChildren = !!node?.categories?.length;
  const categoryType =
    level === 0 ? "category" : !hasChildren ? "leaf" : "group";
  if (!node) return null;
  const { name, key, categories } = node;
  const activeClassName = currentActive === name ? "active" : "";

  return (
    <>
      <div
        className={`list-row level-${level} ${categoryType} ${activeClassName}`}
        onClick={() => {
          setIsOpen((open) => !open);
          if (!hasChildren) {
            setCurrentActive((prevName) => (!(prevName === name) ? name : ""));
          }
        }}
        key={key}
      >
        <div className="list-item-holder">
          {hasChildren && (
            <div className="list-item-expander-holder">
              <span
                className={`expand-collapse-icon ${
                  isOpen ? "collapse" : "expand"
                }`}
              >
                <span className="expand-icon">
                  <FontAwesomeIcon icon="caret-down" />
                </span>
                <span className="collapse-icon">
                  <FontAwesomeIcon icon="caret-right" />
                </span>
              </span>
            </div>
          )}
          <div className="list-item-details-holder">{name}</div>
        </div>
      </div>
      {isOpen && hasChildren && (
        <div className="list-row-children">
          {categories.map((node) => (
            <Node
              key={node.key}
              node={node}
              level={level + 1}
              currentActive={currentActive}
              setCurrentActive={setCurrentActive}
            />
          ))}
        </div>
      )}
    </>
  );
};

到目前为止,我try 的搜索功能并不起作用

 function searchTree(tree, query) {
    function traverse(node, query) {
      if (node.categories) {
        traverse(node.categories, query);
      }
      return {
        ...node,
        categories: node?.categories?.filter(({ name }) => name === query)
      };
    }
    return tree.map((root) => traverse(root, query));
  }

有没有人可以帮助一下如何实现这一点.我还只是个初学者,正在努力学习这一点.如果能帮上忙,我们将不胜感激.

Sandbox 链接:https://codesandbox.io/s/tree-updated-with-search-forked-ms2b6w?file=/src/DrawnTree.jsx:223-617

推荐答案

你是一个铁杆初学者,在我看来,你想要做的事情非常复杂.

我认为这就是您所描述的,许多更改是必要的,我不能解释所有这些更改,最重要的是保持父级打开的逻辑,我创建了一个函数来判断它是否包含带有文本的元素,如果包含,则添加visibleopened属性,将由 node 使用.

另外,我将categories重命名为nodes,我认为这更有意义

https://codesandbox.io/s/tree-updated-with-search-forked-kbnnmj?file=/src/DrawnTree.jsx

  const containsNodesWithTerm = (nodes, searchTerm) => {
    const ids = [];
    const _traverse = (nodes, searchTerm) => {
      nodes.forEach((node) => {
        if (node.name.toUpperCase().includes(searchTerm.toUpperCase())) {
          ids.push(node.key);
        }
        if (node.nodes.length > 0) {
          _traverse(node.nodes, searchTerm);
        }
      });
    };
    _traverse(nodes, searchTerm);
    return ids.length > 0;
  };

  const filterNodes = (nodes, searchTerm = "") => {
    const _filter = (nodes, searchTerm) => {
      nodes.forEach((node) => {
        if (
          node.name.toUpperCase().includes(searchTerm.toUpperCase()) ||
          containsNodesWithTerm(node.nodes, searchTerm)
        ) {
          node.visible = true;
          node.opened = true;
        } else {
          node.visible = false;
        }
        if (!searchTerm) {
          node.opened = false;
        }
        if (node.nodes.length > 0) {
          _filter(node.nodes, searchTerm);
        }
      });
    };
    _filter(nodes, searchTerm);
    return nodes;
  };

Javascript相关问答推荐

v-textfield的规则找不到数据中声明的元素

使用JavaScript更改json值顺序

如何修复内容安全策略指令脚本-SRC自身错误?

将状态向下传递给映射的子元素

MathJax可以导入本地HTML文档使用的JS文件吗?

更改JSON中使用AJAX返回的图像的路径

我在我的Java代码中遇到了问题,代码的一部分看不到先前定义的对象

如何在JavaScript文件中使用Json文件

连接到游戏的玩家不会在浏览器在线游戏中呈现

使用auth.js保护API路由的Next.JS,FETCH()不起作用

Rxjs流中生成IMMER不能在对象上操作

自定义确认组件未在vue.js的v菜单内打开

当代码另有说明时,随机放置的圆圈有时会从画布上消失

FireBase云函数-函数外部的ENV变量

无法重定向到Next.js中的动态URL

react -原生向量-图标笔划宽度

如何修复使用axios运行TSC index.ts时出现的错误?

Node.js API-queryAll()中的MarkLogic数据移动

构建器模式与参数对象输入

对不同目录中的Angular material 表列进行排序