如何在 reactjs 中使用单个 ListItem 映射路由?

Posted

技术标签:

【中文标题】如何在 reactjs 中使用单个 ListItem 映射路由?【英文标题】:How to map routes with individual ListItem in reactjs? 【发布时间】:2020-03-18 17:46:21 【问题描述】:

我正在尝试在我的 react 前端项目中使用材料 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>

但它只能让我转到列表中每个项目的相同链接。如何将单个列表项映射到单个路由?

【问题讨论】:

【参考方案1】:

我找到了实现这一目标的方法。 首先,我创建了一个对象数组,例如:

 const topics= [
      topic: "Home",
      path: "home"
  ,

    topic: "DataStructures",
    path: "datastructures"
]

然后我这样做了:

<List>
          topics.map((text, index) => (
            <ListItem button key=text.topic component="a" href=text.path === "home"? "\\":text.path>
              <ListItemIcon>index % 2 === 0 ? <InboxIcon /> : <MailIcon /></ListItemIcon>
              <ListItemText primary=text.topic />
            </ListItem>
          ))
        </List>

【讨论】:

您走在正确的轨道上,但这只是开始。如果你不集中相关路由的东西,那么万一你的项目变得很大,你可能会遇到麻烦 我是 react 新手,你能给我推荐一个相同的参考吗?【参考方案2】:

我已经整理了一个小样本。这种结构适用于我的所有项目,一旦你掌握了它,就可以很快实施。

Demo link

路线结构

这个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:侧边栏上显示的文本。 (必填) 图标:通常这个图标只显示在侧边栏上。如果您的菜单/侧边栏/导航不需要它,您可以省略它。 (可选) noRender:布尔值,指示此对象是否将渲染到侧边栏。这对于不需要直接访问的路由很有用(例如 404 Page Not Found 页面)(可选) 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>

注意最后一行我明确声明了一个备用&lt;Route /&gt; 路径,以防用户位于错误/未定义的路径上,这就是对象在这种情况下的用处。它不需要path 道具。

你的侧边栏只是一个简单的组件接收一个路由列表作为道具(在app.js中转换),然后它可以用来显示在视图上。

<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 使&lt;Register /&gt; 显示出来。 /page-not-found 也是如此。或者即使你输入了错误的地址,比如/register-user&lt;PageNotFound /&gt; 组件也将用于后备情况。

您可能想知道为什么我不将所有路径路由和路径 ID 放在自己的位置,为什么我需要将它们移动到单独的对象中?答案是,就我而言,我通常需要快速访问这些值。这对于生成面包屑或在不拉动整个对象的情况下进行一些迭代可能很有用。根据您的具体项目需求,这两个可能会缩短。

完整代码,请访问:Sample Link

【讨论】:

以上是关于如何在 reactjs 中使用单个 ListItem 映射路由?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 reactjs 的 localStorage 键上的单个数组中附加用户输入?

如何在 Reactjs 中显示子菜单?

如何在不刷新页面的情况下在 ReactJS 中重新加载?

如何在 reactjs 中同时播放 mp4 和 hls 视频?

需要在通过map函数reactjs编写的元素数组中触发单个元素

如何将索引连接到 Reactjs 元素中的函数