前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >material Tree组件的前端模糊搜索

material Tree组件的前端模糊搜索

作者头像
biaoblog.cn 个人博客
发布2022-11-14 16:50:35
1K0
发布2022-11-14 16:50:35
举报
文章被收录于专栏:web技术开发分享

首先说下我们的需求:

根据materialUI组件的treeView 来进行前端的模糊搜索

展开所选节点所在的父节点,

同时所匹配到的节点高亮显示

思路:需要先把全部的树节点平铺到一层,

然后根据所选择的子节点(这里场景是搜索,可以是多个子节点),

循环遍历多个所选择的子节点,

然后写一个递归函数,依次传递所选择节点的parsentid,

去跟已经平铺到一层的全部节点进行对比,parsentid === id 则添加到父节点的数组中,

然后再传递 已经匹配上的 全部节点中的 那一个节点 (因为父节点还可能拥有父节点),进行递归。

具体的代码:

代码语言:javascript
复制
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import TreeView from '@material-ui/lab/TreeView';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import TreeItem from '@material-ui/lab/TreeItem';

const data = [
  {
    id: 93,
    label: 'USA',
    labelCn: 'USA',
    value: 93,
    children: [
      {
        id: 94,
        label: 'US Citizen',
        labelCn: 'US Citizen',
        value: 94,
        parentId: 93,
        checked: false,
      },
      {
        id: 95,
        label: 'Green Card',
        labelCn: 'Green Card',
        value: 95,
        parentId: 93,
        checked: false,
      },
      {
        id: 96,
        label: 'Working Visa',
        labelCn: 'Working Visa',
        value: 96,
        children: [
          {
            id: 97,
            label: 'H',
            labelCn: 'H',
            value: 97,
            parentId: 96,
            checked: false,
          },
          {
            id: 98,
            label: 'L',
            labelCn: 'L',
            value: 98,
            parentId: 96,
            checked: false,
          },
          {
            id: 99,
            label: 'O',
            labelCn: 'O',
            value: 99,
            parentId: 96,
            checked: false,
            children: null,
          },
          {
            id: 9999,
            label: 'WW',
            labelCn: 'WW',
            value: 9999,
            parentId: 96,
            checked: false,
            children: null,
          },
        ],
        parentId: 93,
        checked: false,
      },
      {
        id: 100,
        label: 'EAD Card',
        labelCn: 'EAD Card',
        value: 100,
        children: [
          {
            id: 101,
            label: 'OPT/STEM OPT',
            labelCn: 'OPT/STEM OPT',
            value: 101,
            parentId: 100,
            checked: false,
          },
          {
            id: 102,
            label: 'Asylum',
            labelCn: 'Asylum',
            value: 102,
            parentId: 100,
            checked: false,
          },
          {
            id: 103,
            label: 'H4-EAD',
            labelCn: 'H4-EAD',
            value: 103,
            parentId: 100,
            checked: false,
          },
          {
            id: 104,
            label: 'J2-EAD',
            labelCn: 'J2-EAD',
            value: 104,
            parentId: 100,
            checked: false,
          },
          {
            id: 105,
            label: 'L2-EAD',
            labelCn: 'L2-EAD',
            value: 105,
            parentId: 100,
            checked: false,
          },
          {
            id: 106,
            label: '485 EAD',
            labelCn: '485 EAD',
            value: 106,
            parentId: 100,
            checked: false,
          },
        ],
        parentId: 93,
        checked: false,
      },
    ],
    parentId: 0,
    checked: false,
  },
  {
    id: 107,
    label: 'Canada',
    labelCn: 'Canada',
    value: 107,
    children: [
      {
        id: 108,
        label: 'Canadian Citizen',
        labelCn: 'Canadian Citizen',
        value: 108,
        parentId: 107,
        checked: false,
      },
      {
        id: 109,
        label: 'Permanent Resident',
        labelCn: 'Permanent Resident',
        value: 109,
        parentId: 107,
        checked: false,
      },
      {
        id: 110,
        label: 'Open Work Permit',
        labelCn: 'Open Work Permit',
        value: 110,
        parentId: 107,
        checked: false,
      },
      {
        id: 111,
        label: 'Student Visa',
        labelCn: 'Student Visa',
        value: 111,
        parentId: 107,
        checked: false,
      },
    ],
    parentId: 0,
    checked: false,
  },
  {
    id: 112,
    label: 'Europe',
    labelCn: 'Europe',
    value: 112,
    children: [
      {
        id: 113,
        label: 'Citizen',
        labelCn: 'Citizen',
        value: 113,
        parentId: 112,
        checked: false,
      },
      {
        id: 114,
        label: 'Permanent Resident',
        labelCn: 'Permanent Resident',
        value: 114,
        parentId: 112,
        checked: false,
      },
      {
        id: 115,
        label: 'Work permit with restrictions',
        labelCn: 'Work permit with restrictions',
        value: 115,
        parentId: 112,
        checked: false,
      },
      {
        id: 116,
        label: 'Student Visa',
        labelCn: 'Student Visa',
        value: 116,
        parentId: 112,
        checked: false,
      },
    ],
    parentId: 0,
    checked: false,
  },
];

const useStyles = makeStyles({
  root: {
    height: 110,
    flexGrow: 1,
    maxWidth: 400,
  },
});

export default function RecursiveTreeView() {
  const classes = useStyles();
  const [expanded, setExpanded] = React.useState([]);
  const [selected, setSelected] = React.useState([]);

  const setTreeLabel = (node) => {
    return (
      <div>
        <span>
          {node.label} - {node.id}
        </span>
      </div>
    );
  };

  const renderTree = (nodes) =>
    nodes.map((item, index) => {
      return (
        <TreeItem
          key={item.id}
          setChecked={(item) => {
            setChecked(item);
          }}
          nodeId={`${item.id}`}
          item={item}
          label={setTreeLabel(item)}
        >
          {item.children ? renderTree(item.children) : null}
        </TreeItem>
      );
    });

  const handleToggle = (event, nodeIds) => {
    setExpanded(nodeIds);
  };

  const handleSelect = (event, nodeIds) => {
    setSelected(nodeIds);
  };

  let timer = null;

  const search = (e) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      let value = e.target.value;
      let expanded = [];
      let selected = [];
      if (value) {
        selected = findNodes(data, value, []);
        expanded = findParsent(selected);
      }
      setSelected(selected.map((n) => String(n.id)));
      setExpanded(expanded.map((n) => String(n.id)));
    }, 100);
  };

  const setSpreadTreeData = (tree, data = []) => {
    for (let i = 0; i < tree.length; i++) {
      let item = tree[i];
      data.push(item);
      item.children && setSpreadTreeData(item.children, data);
    }
    return data;
  };

  const findNodes = (data, value, arr) => {
    for (let node of data) {
      if (node.label.toUpperCase().includes(value.toUpperCase())) {
        arr.push(node);
      }
      if (node.children) {
        findNodes(node.children, value, arr);
      }
    }
    return arr;
  };

  const findParsent = (selected) => {
    let spreadTreeData = setSpreadTreeData(data);
    let parsentNodes = [];
    let dist = (parentId, arr) => {
      for (let s of spreadTreeData) {
        if (s.id == parentId) {
          arr.push(s);
          if (s.parentId) {
            dist(s.parentId, arr);
          }
        }
      }
      return arr;
    };
    for (let s of selected) {
      parsentNodes = dist(s.parentId, parsentNodes);
    }
    return parsentNodes;
  };

  return (
    <div>
      <input type="text" onChange={search} />
      <TreeView
        className={classes.root}
        defaultCollapseIcon={<ExpandMoreIcon />}
        defaultExpanded={['root']}
        defaultExpandIcon={<ChevronRightIcon />}
        expanded={expanded}
        selected={selected}
        onNodeToggle={handleToggle}
        multiSelect
        onNodeSelect={handleSelect}
      >
        {renderTree(data)}
      </TreeView>
    </div>
  );
}

效果图:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档