我想创建多级嵌套列表以在左侧显示菜单 - - 与官方网站非常相似:https://material-ui-next.com/。数据源在 JSON 中,其中每个项目还有有关父项目和其他一些数据的信息 - - 这是示例:
{
"task_number": 1201092,
"task": "Monthly Cash Flow from Deliveries",
"task_parent_number": 1201090,
"task_parent": "Wholesale Cash Flow"
},
{
"task_number": 1201095,
"task": "Monthly Cash Flow from Fix Amounts",
"task_parent_number": 1201090,
"task_parent": "Wholesale Cash Flow"
},
{
"task_number": 1201100,
"task": "Wholesale Positions",
"task_parent_number": 1200007,
"task_parent": "Wholesale Contract Portfolio"
},
{
"task_number": 1201200,
"task": "All Wholesale Positions",
"task_parent_number": 1201100,
"task_parent": "Wholesale Positions"
}
我能够创建一个带有各种嵌套元素的对象 - 孩子 - 如果它们存在 followin 函数:
function getNestedChildren(arr, parent) {
var out = [];
for (var i in arr) {
if (arr[i].task_parent_number == parent) {
//console.log(i, arr[i].task_parent_number, arr[i].task_number);
var children = getNestedChildren(arr, arr[i].task_number);
if (children.length) {
arr[i].children = children;
}
out.push(arr[i]);
}
}
return out;
}
我一直在按照说明创建嵌套列表并将其导入到此处:https://material-ui-next.com/demos/lists/#nested-list
..但我无法根据需要创建带有嵌套元素的菜单..如果有人能指出我正确的方向,那就太好了。
好的,我把它结合起来,将这两个部分结合起来:
- 反应示例递归渲染:https://gist.github.com/nkvenom/bf7b1adfe982cb47dee3
- 材料列表指南在这里 - https://medium.com/@ali.atwa/getting-started-with-material-ui-for-react-59c82d9ffd93
有 mui 组件。
我在最后一个示例中添加了递归。
import type { SvgIconProps } from '@mui/material/SvgIcon';
import * as React from 'react';
import { styled } from '@mui/material/styles';
import Box from '@mui/material/Box';
import TreeView, { TreeViewProps } from '@mui/lab/TreeView';
import TreeItem, { TreeItemProps, treeItemClasses } from '@mui/lab/TreeItem';
import Typography from '@mui/material/Typography';
// import DeleteIcon from '@mui/icons-material/Delete';
// import Label from '@mui/icons-material/Label';
// import SupervisorAccountIcon from '@mui/icons-material/SupervisorAccount';
// import InfoIcon from '@mui/icons-material/Info';
// import ForumIcon from '@mui/icons-material/Forum';
// import LocalOfferIcon from '@mui/icons-material/LocalOffer';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
declare module 'react' {
interface CSSProperties {
'--tree-view-color'?: string;
'--tree-view-bg-color'?: string;
}
}
type StyledTreeItemProps = TreeItemProps & {
bgColor?: string;
color?: string;
labelIcon?: React.ElementType<SvgIconProps>;
labelInfo?: React.ReactNode;
labelText: string;
};
type RecursiveStyledTreeItemProps = StyledTreeItemProps & {
childrenProps?: RecursiveStyledTreeItemProps[]
}
const StyledTreeItemRoot = styled(TreeItem)(({ theme }) => ({
color: theme.palette.text.secondary,
[`& .${treeItemClasses.content}`]: {
color: theme.palette.text.secondary,
borderTopRightRadius: theme.spacing(2),
borderBottomRightRadius: theme.spacing(2),
paddingRight: theme.spacing(1),
fontWeight: theme.typography.fontWeightMedium,
'&.Mui-expanded': {
fontWeight: theme.typography.fontWeightRegular,
},
'&:hover': {
backgroundColor: theme.palette.action.hover,
},
'&.Mui-focused, &.Mui-selected, &.Mui-selected.Mui-focused': {
backgroundColor: `var(--tree-view-bg-color, ${theme.palette.action.selected})`,
color: 'var(--tree-view-color)',
},
[`& .${treeItemClasses.label}`]: {
fontWeight: 'inherit',
color: 'inherit',
},
},
[`& .${treeItemClasses.group}`]: {
marginLeft: 0,
[`& .${treeItemClasses.content}`]: {
paddingLeft: theme.spacing(2),
},
},
}));
const RecursiveStyledTreeItem = ({ childrenProps, ...p }: RecursiveStyledTreeItemProps) => childrenProps
? <RecursiveStyledTreeItem {...p}>
{
childrenProps.map(cP => <RecursiveStyledTreeItem
key={cP.nodeId}
{...cP}
/>)
}
</RecursiveStyledTreeItem>
: < StyledTreeItem {...p} />
function StyledTreeItem(props: StyledTreeItemProps) {
const {
bgColor,
color,
labelIcon: LabelIcon = null,
labelInfo = null,
labelText,
...other
} = props;
return (
<StyledTreeItemRoot
label={
<Box sx={{ display: 'flex', alignItems: 'center', p: 0.5, pr: 0 }}>
{
LabelIcon && <Box component={LabelIcon} color="inherit" sx={{ mr: 1 }} />
}
<Typography variant="body2" sx={{ fontWeight: 'inherit', flexGrow: 1 }}>
{labelText}
</Typography>
{
labelInfo && <Typography variant="caption" color="inherit">
{labelInfo}
</Typography>
}
</Box>
}
style={{
'--tree-view-color': color,
'--tree-view-bg-color': bgColor,
}}
{...other}
/>
);
}
export default function CustomTreeView({ treeViewProps, items }: {
treeViewProps: Partial<TreeViewProps>
items: RecursiveStyledTreeItemProps[]
}) {
return (
<TreeView
// defaultExpanded={['3']}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<div style={{ width: 24 }} />}
sx={{ height: 264, flexGrow: 1, maxWidth: 400, overflowY: 'auto' }}
{...treeViewProps}
>
{items.map(item => <RecursiveStyledTreeItem
key={item.nodeId}
{...item}
/>)}
</TreeView>
);
}
有梅树选择