React Tree结构Demo

该文章展示了如何在React中使用Tree结构来创建一个多级菜单系统。代码包括定义TreeItem接口来描述树节点,以及两个组件:Menus和MenuItem,用于渲染和交互。文章还提供了一个完整的示例项目链接,该项目实现了菜单的展开和收缩功能。
摘要由CSDN通过智能技术生成

要实现的功能
请添加图片描述

请添加图片描述
请添加图片描述
请添加图片描述请添加图片描述
使用的Tree结构

import set from '@/assets/set.png';
import info from '@/assets/info.png';
import show from '@/assets/flower.png';
import pinkFlower from '@/assets/pinkFlower.png';
import Yh from '@/assets/Yh.png';

import sevenColouredFlowers from '@/assets/sevenColouredFlowers.png';

export interface TreeItem {
  title: string;
  key: string;
  level: string;
  display?: boolean;
  children?: TreeItem[];
  desc?: string;
  icon?: string;
}

export const node: TreeItem[] = [
  {
    title: '111111',
    key: '0',
    level: 'level1',
    display: true,
    icon: info
  },
  {
    title: '00000',
    key: '0',
    level: 'level1',
    display: true,
    icon: set,
    children: [
      {
        title: '0-111111',
        key: '0-0',
        level: 'level2',
        display: true,
        icon: show,
        children: [
          {
            title: '0-1-1111',
            key: '0-0-0',
            level: 'level3',
            icon: pinkFlower,
          },
          {
            title: '0-1-2222',
            key: '0-0-1',
            level: 'level3',
            display: true,
            icon: pinkFlower,
            children: [
              {
                title: '0-1-2-11111',
                key: '0-0-1-0',
                level: 'level4',
                display: true,
                icon: Yh,
                children: [
                  {
                    title: '0-1-2-1-111',
                    key: '0-0-1-0-0',
                    level: 'level5',
                    icon: sevenColouredFlowers,
                  }
                ]
              }
            ]
          },
          {
            title: '0-1-33333',
            key: '0-0-4',
            level: 'level3',
            icon: pinkFlower,
          },
        ]
      },
      {
        title: '0-222222',
        key: '0-2',
        level: 'level2',
        display: true,
        icon: show,
        children: [
          {
            title: '0-2-1111',
            key: '0-2-0',
            level: 'level3',
            icon: pinkFlower,
          },
          {
            title: '0-2-2222',
            key: '0-2-0',
            level: 'level3',
            icon: pinkFlower,
          },
          {
            title: '0-2-3333',
            key: '0-2-0',
            level: 'level3',
            icon: pinkFlower,
          }
        ]
      }
    ]
  }
]

代码

import { useRef } from "react";
import styles from './treeMenuList.module.less';
import dropdown from '@/assets/dropdown.png';
// import { useNavigate, useParams } from "react-router-dom";
import { TreeItem } from './treeData';



interface MenusProps {
  menu: TreeItem
}

export function Menus(props: MenusProps) {
  const { menu } = props;
  const ulRef = useRef<HTMLDivElement>(null);

  function onDisplayMenuItemList(e: any) {
    e.stopPropagation();
    // 这是点击➡️ 时调用的方法
    // 如果当前这个➡️ 没有旋转,那就设置旋转,视觉效果

    e.target.style.transform = e.target.style.transform === 'rotate(0deg)' ? 'rotate(180deg)' : 'rotate(0deg)'
    let ul = e.target.parentNode.parentNode.parentNode.parentNode.parentNode;
    for (let i = 1; i < ul.children.length; i++) {
      ul.children[i].style.display = ul.children[i].style.display === "none" ? "block" : 'none'
    }
  }

  function tree(children: TreeItem[] | undefined) {
    let treeItem;
    //如果有子元素
    if (children) {
      //子元素是数组的形式,把所有的子元素循环出来
      treeItem = children.map((item: TreeItem, key: number) => {
        return (
          <ul key={key} >
            <li>
              <MenuItem menuItem={item} onDisplayMenuItemList={onDisplayMenuItemList} />
            </li>
            {/* 如果当前子元素还有子元素,就递归使用tree方法,把当前子元素的子元素渲染出来 */}
            {tree(item.children)}
          </ul>
        )
      })
    }
    return treeItem;
  }

  function treeItemGroup(itemGroup: any) {
    let itemGroupItem = [];
    // 把所有节点放在一个数组里面
    itemGroupItem.push(
      <main>
        {/* 第一个层级 */}
        <li key={itemGroup.key} >
          <MenuItem menuItem={itemGroup} onDisplayMenuItemList={onDisplayMenuItemList} />
        </li>
        {/* 调用tree方法 */}
        {tree(itemGroup.children)}
      </main>
    )
    return itemGroupItem
  }


  return (
    <div className={styles.menus} ref={ulRef}>
      {treeItemGroup(menu)}
    </div>
  )
}
interface MenuItemProps {
  menuItem: TreeItem;
  onDisplayMenuItemList?: any
}

export function MenuItem(props: MenuItemProps) {
  const { menuItem, onDisplayMenuItemList } = props;
  // const nav = useNavigate();

  function onEnterMenuItem() {
    // nav(`m/${menu.name}`, { replace: true })
  }
  return (
    <div className={styles.menuItem}>
      <div className={styles.mLeft}>
        <img src={menuItem?.icon} className={styles.avatar} alt="" />
      </div>
      <div className={styles.mRight} onClick={onEnterMenuItem}>
        <div className={styles.rLeft}>
          <h3>{menuItem?.title}</h3>
        </div>
        {menuItem.children &&
          <div className={styles.rRight} onClick={(e) => onDisplayMenuItemList(e)}>
            <img src={dropdown} alt="" className={styles.dropdown} />
          </div>
        }
      </div>
    </div>
  )
}

完整示例:https://github.com/1linan/react_tree_demo 如果此案例对您有帮助,那就点个star吧,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值