要实现的功能
使用的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吧,谢谢