React Router:关于嵌套路由的简单教程。

2025-06-08

React Router:关于嵌套路由的简单教程。

大家好,

React Router Dom 是使用 ReactJS 时必须了解的库之一。不久前,我遇到了 React Routing 的一个非常常见的用例,其中存在多层嵌套的路由。起初我非常困惑,因为 React Router 简单的嵌套路由模式对我来说行不通。我不得不实现嵌套高达 3 层的路由。

这在使用 React App 时是一个非常常见的用例,所以我想在这里分享我的路由方法。那么,让我们开始吧。

在本教程中,我使用 创建了一个简单的项目,create-react-appreact-router-dom使用 添加了代码npm。由于这些步骤非常基础,因此我不会将它们包含在本文中。如果您想跳过本教程并直接查看代码,可以查看我的GitHub 仓库

因此,我们将创建一个外观简洁的仪表板,它将包含一个带有页面链接的通用侧边栏。其中一个页面顶部将有一个单独的导航栏,可以直接跳转到其他页面。我们还将创建一个登录页面,我们将从该页面进入仪表板内部。很简单,对吧?附言:
本教程不涉及任何登录系统或路由授权,因为这超出了本教程的范围。

路由将从BrowserRouter向应用添加 开始。因此,在 中App.js,将完整的代码包装到 中BrowserRouter。现在,让我们创建一个非常简单的登录页面,以开始使用该应用。

import { Link } from 'react-router-dom';

const Login = (props) => {
    return (
    <>
       <div className='login'>
        <p>Login to the app</p>
        <Link to='/home' className='button'>
            Login
        </Link>
       </div>
    </>
    );
};
export default Login;
Enter fullscreen mode Exit fullscreen mode

这里我们只是创建一个按钮来实现登录的效果。这个按钮会链接到/home剩余应用所在的页面。

现在,为了继续前进,我们将为应用创建并定义其他路由。在这个应用中,我们将使用一个单独的注册表来定义路由。我将其命名为Routes.js

在 React Router 中,声明路由的常用方法是定义一个组件以及该路由的路径。因此,我们将创建一个对象数组,其中每个对象代表一个路由。对于一些基本的路由,我们的Routes.js路由结构如下所示:

import Home from './Home';
import Login from './Login';

const routes = [
    {
    path: '/login',
    component: Login,
    },
    {
    path: '/home',
    component: Home,
    },
];

export default routes;
Enter fullscreen mode Exit fullscreen mode

在这里,我们的 Home 组件是我们应用内的根组件。现在,我们需要添加 Home 组件的嵌套。在 Home 组件内部,我们将有一个公共侧边栏和一个主页面,我们将在该主页面中渲染侧边栏中的所有页面。

因此,我们的下一个需求是将这些页面从 home 组件添加为嵌套路由。为了创建这些嵌套路由,我们将创建一个类似的路由数组,就像上面创建的一样,但位于 Home 组件内部。React Router Dom 为每个 Route 组件添加了一个名为 routes 的属性,该属性将包含所有嵌套路由的列表。让我们用 Home 组件中的一些页面来更新我们的路由组件。

因此,我们的路线看起来是这样的:

import Home from './Home';
import Login from './Login';
import Page1 from './pages/Page1';
import Page2 from './pages/Page2';

const routes = [
    {
    path: '/login',
    component: Login,
    },
    {
    path: '/home',
    component: Home,
    // added nested routes
    routes: [              
        {
        // Also note how we added /home before the 
        // actual page name just to create a complete path
        path: '/home/page1',
        component: Page1,
        },
        {
        path: '/home/page2',
        component: Page2,
        },
    ],
    },
];

export default routes;
Enter fullscreen mode Exit fullscreen mode

到目前为止,我们已经创建了一些嵌套路由,但这些路由尚未在我们的应用程序内部配置。因此,让我们将它们添加到App.jsinside 中BrowserRouter

import { BrowserRouter, Redirect, Switch } from 'react-router-dom';
import routes from './Routes';
import RouteWithSubRoutes from './utils/RouteWithSubRoutes';

function App() {
    return (
    <BrowserRouter>
        <Switch>
        <Redirect exact from='/' to='/login' />
        {routes.map((route, i) => (
            <RouteWithSubRoutes key={i} {...route} />
        ))}
        </Switch>
    </BrowserRouter>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

的代码App.js很简单。我们添加了BrowserRouter一个“开关”。我们将应用程序从 重定向//login,然后加载所有路由。

map 函数只是迭代 routes 数组,但现在你可以看到一个有趣的组件RouteWithSubRoutes。让我们了解一下它内部做了什么。

import { Route } from 'react-router-dom';

const RouteWithSubRoutes = (route) => {
    return (
    <Route
        path={route.path}
        render={(props) => (
            <route.component {...props} routes={route.routes} />.
        )}
    />
    );
};

export default RouteWithSubRoutes;

Enter fullscreen mode Exit fullscreen mode

这里我们只是返回同一个组件,但需要注意的是,我们将所有子路由都传递给了该组件。因此,父路由始终能够感知到它的所有子路由。

好了,我们的路由已经排序好了,app 组件也排序好了。现在,我们需要看看 home 组件是如何管理我们刚刚传递给它的所有子路由的。

这是我们的 Home 组件:

import { Switch, Link } from 'react-router-dom';
import RouteWithSubRoutes from './utils/RouteWithSubRoutes';

// Notice how we are passing routes here 
const Home = ({ routes }) => {
    const menu = [
    {
        path: '/home/page1', // the url
        name: 'Page1', // name that appear in Sidebar
    },
    {
        path: '/home/page2',
        name: 'Page2',
    },
    ];
    return (
    <div className='home'>
    {/* This can be treated as a sidebar component */}
        <div className='sidebar'>
        <h2>React Nested Routes</h2>
        <ul>
            {menu.map((menuItem) => (
            <li key={menuItem.name}>
                <Link to={menuItem.path}>{menuItem.name}</Link>
            </li>
            ))}
        </ul>
        </div>

        <Switch>
        {routes.map((route, i) => (
            <RouteWithSubRoutes key={i} {...route} />
        ))}
        </Switch>
    </div>
    );
};

export default Home;

Enter fullscreen mode Exit fullscreen mode

Home 组件与任何常见的 React 组件类似。我们在这里创建了一个数组来显示侧边栏,并添加了指向该侧边栏内所有页面的链接。其中一个Switch用于渲染用户点击侧边栏时选择的组件,另一个则使用同一个RouteWithSubRoutes组件来传递后续的子路由(如果有)。

这里需要注意的一点是,路由会像 props 一样传递给 Home 组件。这样,Home 组件就能始终感知到它的子组件,路由也就永远不会出错了!

您可以根据需要使用相同的方法在应用中嵌套更多层级。在GitHub 仓库中,我还为一个页面添加了导航栏。您可以查看一下。

React Router 的官方文档中也有一个类似的例子

这就是关于 React 嵌套路由的全部内容!如果你对此有不同的做法,请在评论区告诉我。

如果您喜欢我的文章,您还可以通过Twitter与我联系给我买杯咖啡。

继续学习!

鏂囩珷鏉ユ簮锛�https://dev.to/hey_yogini/react-router-a-simple-tutorial-on-nested-routes-1237
PREV
使用 React 和 Tailwind 的简单进度条组件
NEXT
作为开发人员处理倦怠!