Yog*_*mar 1 reactjs material-ui
I am trying to develop a sidebar menu using material ui. I am able to make it for simple list. In my project I have a requirement of nested sidebar menu which I am not able to achieve. If I am trying to use recursive function it is providing only main title menu and not rendering child elements. Please help me develop it.
The code for nested sidebar menu is as below,
import React, {useState} from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Collapse from '@material-ui/core/Collapse';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
nested: {
paddingLeft: theme.spacing(4),
},
}));
export const Menu = ({items}) => {
const classes = useStyles();
const [open, setOpen] = useState(true);
const handleClick = () => {
setOpen(!open);
};
return (
items.map(item =>
!item.children ? (
<div key={item.title}>
<ListItem button>
<ListItemIcon>
{item.icon}
</ListItemIcon>
<ListItemText primary={item.title} />
</ListItem>
</div>
) : (
<div
component="nav"
key={item.title}
>
<ListItem button onClick={handleClick}>
<ListItemIcon>
{item.icon}
</ListItemIcon>
<ListItemText primary={item.title} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem button className={classes.nested}>
<ListItemIcon>
{item.icon}
</ListItemIcon>
<ListItemText>
<Menu items={item} />
</ListItemText>
</ListItem>
</List>
</Collapse>
</div>
)
)
);
}
Run Code Online (Sandbox Code Playgroud)
menu item code is here,
import HomeOutlinedIcon from "@material-ui/icons/HomeOutlined";
import LocalLibraryOutlinedIcon from "@material-ui/icons/LocalLibraryOutlined";
import TrendingUpOutlinedIcon from "@material-ui/icons/TrendingUpOutlined";
import DescriptionOutlinedIcon from "@material-ui/icons/DescriptionOutlined";
import React from "react";
export const menu = [
{
icon: <HomeOutlinedIcon/>,
title: 'Home',
items: []
},
{
icon: <LocalLibraryOutlinedIcon/>,
title: 'Education',
items: [
{
title:'Technical Analysis',
items: [
{
title: 'The Dow Theory',
to: '/thedowtheory'
},
{
title: 'Charts & Chart Patterns',
to: '/chart'
},
{
title: 'Trend & Trend Lines',
to: '/trendlines'
},
{
title: 'Support & Resistance',
to: '/sandr'
},
]
},
{
title:'Fundamental Analysis',
items: [
{
title: 'The Dow Theory',
to: '/thedowtheory'
},
{
title: 'Charts & Chart Patterns',
to: '/chart'
},
{
title: 'Trend & Trend Lines',
to: '/trendlines'
},
{
title: 'Support & Resistance',
to: '/sandr'
},
]
},
{
title:'Elliot Wave Analysis',
items: [
{
title: 'The Dow Theory',
to: '/thedowtheory'
},
{
title: 'Charts & Chart Patterns',
to: '/chart'
},
{
title: 'Trend & Trend Lines',
to: '/trendlines'
},
{
title: 'Support & Resistance',
to: '/sandr'
},
]
},
]
},
{
icon: <TrendingUpOutlinedIcon/>,
title: 'Options'
},
{
icon: <DescriptionOutlinedIcon/>,
title: 'Blog'
},
]
Run Code Online (Sandbox Code Playgroud)
首先,你有一个错字。你在children
key 而不是items
. 但即使您修复了该问题,您的代码仍不会按照您想要的方式工作。
我将通过创建一个简化我的做法SingleLevel
和MultiLevel
可重复使用的组件来处理当前菜单项。如果当前项目有children
/items
那么我会使用MultiLevel
组件 else SingleLevel
。
单层组件
const SingleLevel = ({ item }) => {
return (
<ListItem button>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText primary={item.title} />
</ListItem>
);
};
Run Code Online (Sandbox Code Playgroud)
多级组件
const MultiLevel = ({ item }) => {
const { items: children } = item;
const [open, setOpen] = useState(false);
const handleClick = () => {
setOpen((prev) => !prev);
};
return (
<React.Fragment>
<ListItem button onClick={handleClick}>
<ListItemIcon>{item.icon}</ListItemIcon>
<ListItemText primary={item.title} />
{open ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{children.map((child, key) => (
<MenuItem key={key} item={child} />
))}
</List>
</Collapse>
</React.Fragment>
);
};
Run Code Online (Sandbox Code Playgroud)
为了确定要使用哪个组件,然后我将创建一个hasChildren
辅助函数,true
如果当前项满足我定义的所有条件以被视为父菜单项,则该函数返回。
实用程序.js
export function hasChildren(item) {
const { items: children } = item;
if (children === undefined) {
return false;
}
if (children.constructor !== Array) {
return false;
}
if (children.length === 0) {
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
然后我会将所有这些抽象到另一个MenuItem
组件上。
菜单项组件
const MenuItem = ({ item }) => {
const Component = hasChildren(item) ? MultiLevel : SingleLevel;
return <Component item={item} />;
};
Run Code Online (Sandbox Code Playgroud)
最后,这是我将如何循环menu
项目
export default function App() {
return menu.map((item, key) => <MenuItem key={key} item={item} />);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4658 次 |
最近记录: |