我正在尝试在我的 React 前端元素中使用 Material Ui。我已经实现了 AppBar 和抽屉组件,它们工作得很好。这是我到目前为止所取得的成就:
export default function MiniDrawer() {
const classes = useStyles();
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<div className={classes.root}>
<CssBaseline />
<AppBar style={{background: 'black'}}
position="fixed"
className={clsx(classes.appBar, {
[classes.appBarShift]: open,
})}
>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
className={clsx(classes.menuButton, {
[classes.hide]: open,
})}
>
<MenuIcon />
</IconButton>
<Typography className={classes.mystyle} variant="h5" >
CodeBasics
</Typography>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
className={clsx(classes.drawer, {
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
})}
classes={{
paper: clsx({
[classes.drawerOpen]: open,
[classes.drawerClose]: !open,
}),
}}
open={open}
>
<div className={classes.toolbar}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
</div>
<Divider />
<List>
{['Home', 'Algorithms', 'DataStructures'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
</Drawer>
<main className={classes.content}>
<div className={classes.toolbar} />
<Layout>
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/DataStructures" component={DataStructures} />
</Switch>
</Router>
</Layout>
</main>
</div>
);
}
现在我想用不同的路径映射每个“Home”、“DataStructures”和“Algorithms”。我已经实现了一种以这种方式路由 List 组件的方法。
<List>
{['Home', 'Algorithms', 'DataStructures'].map((text, index) => (
<ListItem button key={text} component="a" href="www.google.com">
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
但它只会让我转到列表中每个元素的相同链接。如何将单个列表项映射到单个路由?
最佳答案
我整理了一个小样本。这种结构适用于我的所有元素,一旦掌握了它,实现起来会非常快。
路由结构
这pathIds
变量是一个对象,其中包含路由的所有 id 值。这在需要引用以自动生成面包屑链接时非常有用。
const pathIds = {
home: 'home',
...
}
这pathRouting
变量是一个对象,它包含所有路径路由。只是路径路由。
const pathRouting = {
home: '/home',
...
}
一级结构对象:
const pageRoutes = {
[pathIds.home]: {
path: pathRouting.home,
sidebarName: 'Homepage',
icon: Dashboard,
noRender: false,
component: Home,
},
...
}
这是主要结构对象,包含生成到 HTML 上的所有必要信息(边栏、面包屑、路线等)。
- path:从
pathRouting
获取路径值目的。 (必填) - sideName:显示在边栏上的文本。 (必填)
- icon:通常这个图标只显示在侧边栏上。如果您的菜单/侧边栏/导航不需要它,您可以省略它。 (可选)
- noRender: bool 值,指示是否将此对象渲染到侧边栏。这对于不需要直接访问的路由很有用(例如 404 页面未找到页面)(可选)
- component:将用于呈现的 React 组件。 (必填)
然后,在您的 app.js
中, 你导入 pageRoutes
照常。在进行映射或迭代工作之前,您可能需要将此对象转换为数组(或使用类似 lodash
的库直接迭代对象)。
const routeArray = Object.values(pageRoutes);
然后:
<Switch>
{routeArray.map((prop, key) => {
return (
<Route
path={prop.path}
component={prop.component}
exact={prop.exact || false}
key={`route-${key}`}
/>
);
})}
<Route component={pageRoutes[pathIds.error404].component} />
</Switch>
请注意最后一行我明确声明了回退 <Route />
万一用户在错误/未定义的路径上,这就是对象在这种情况下的用处。它不需要 path
Prop 。
侧边栏只是一个简单的组件,接收路由列表作为 Prop (在 app.js
中转换),然后它可以用于在 View 上显示。
<List component="nav" aria-label="main mailbox folders">
{routes.map(({ path, noRender, sidebarName, ...prop }, index) => {
if (noRender) return null;
return (
<NavLink to={path} key={`route-${index}}`}>
<ListItem button>
<ListItemIcon>
<prop.icon />
</ListItemIcon>
<ListItemText primary={sidebarName} />
</ListItem>
</NavLink>
);
})}
</List>
你会看到它只渲染 Homepage, Inbox and Reset Password
在侧边栏上。但是可以直接输入/register
制作<Register />
出现。 /page-not-found
相同.甚至当您输入错误的地址时,如 /register-user
, <PageNotFound />
组件将用于后备案例。
您可能想知道为什么我不将所有路径路由和路径 ID 放在自己的位置,为什么我需要将它们移动到一个单独的对象中?答案是,就我而言,我通常需要快速访问这些值。这可能有助于生成面包屑或在不拉动整个对象的情况下进行一些迭代。根据您的具体元素需求,这两个可能会缩短。
完整代码,您可以访问这里:Sample Link
关于javascript - 如何在 reactjs 中使用单个 ListItem 映射路由?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58997877/