在现代前端开发中,路由配置 是构建单页应用(SPA)的重要组成部分。React 中最常用的路由库是 react-router-dom
,它帮助我们实现页面之间的跳转和组件的动态加载。 今天我们就来聊一聊 React Router 中的 useRoutes
钩子函数,以及它是如何帮助我们更优雅地配置路由的。
一、传统路由配置方式(使用 JSX)
在 React Router 中,最基础的路由配置方式是通过 <BrowserRouter>
和 <Routes>
+ <Route>
来完成的。例如:
jsx
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import Login from './Pages/Login'
import NoteClass from './Pages/NoteClass'
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Navigate to="/noteClass" />} />
<Route path="/login" element={<Login />} />
<Route path="/noteClass" element={<NoteClass />} />
</Routes>
</BrowserRouter>
)
}
这种方式虽然直观,但当路由很多时,维护起来会变得不太方便,尤其是想动态生成路由 或集中管理路由配置时,就显得不够灵活。
二、useRoutes:用 JS 对象配置路由(更灵活的方式)
React Router v6+ 提供了一个非常好用的钩子函数:useRoutes
,它允许我们使用 JavaScript 对象的方式来定义路由规则,非常适合大型项目或需要动态配置路由的场景。
✅ 使用步骤如下:
1. 引入组件(使用懒加载)
为了提升性能,我们通常会使用 React.lazy()
来实现组件的懒加载,即只有在访问对应路由时才加载组件。如果不使用懒加载,用户打开网页时,会一次性加载所有页面的代码,哪怕他只看首页。用了懒加载之后,只有用户访问某个页面时,才会加载那个页面的组件,这样首页加载更快,用户体验更好。
js
import React from 'react'
const Login = React.lazy(() => import('../Pages/Login'))
const NoteClass = React.lazy(() => import('../Pages/NoteClass'))
⚠️ 每个懒加载的组件都要单独引入。
2. 定义路由配置对象
接下来,我们定义一个 routes
数组,里面是每个路由的配置对象:
js
const routes = [
{
path: '/',
element: <Navigate to="/noteClass" /> // 默认重定向到 /noteClass
},
{
path: '/login',
element: <Login /> // 登录页面
},
{
path: '/noteClass',
element: <NoteClass /> // 主页
}
]
这里用到了
<Navigate>
组件,它是 React Router v6+ 提供的重定向组件,用于将用户从一个路径跳转到另一个路径。如果你没有指定要访问哪个页面,那就自动跳转到/noteClass
。
3. 创建一个封装了 useRoutes 的组件
我们创建一个 WrapperRoutes
函数组件,用来调用 useRoutes
并返回对应的路由元素:
js
import { useRoutes } from 'react-router-dom'
function WrapperRoutes() {
const ele = useRoutes(routes)
return ele
}
但注意:useRoutes
必须在路由上下文中使用 ,也就是说它必须包裹在 <BrowserRouter>
里面。
4. 包裹在 BrowserRouter 中
为了解决上下文的问题,我们再创建一个 WrapperRouter
组件,把 WrapperRoutes
包裹在 <BrowserRouter>
中:
js
import { BrowserRouter } from 'react-router-dom'
export default function WrapperRouter() {
return (
<BrowserRouter>
<WrapperRoutes />
</BrowserRouter>
)
}
三、最终使用方式
现在,我们可以在主组件 App.jsx
中直接使用这个封装好的路由组件:
jsx
import React from 'react'
import WrapperRouter from './router'
import toast, { Toaster } from 'react-hot-toast'
export default function App() {
return (
<>
<WrapperRouter />
<Toaster />
</>
)
}
这样,我们就完成了整个路由的配置。
四、使用扩展
现在如果想把所有和用户相关的页面路径都统一放在 /user/xxx
这样的结构下,比如:
- 用户首页:
/user/home
- 用户资料:
/user/profile
- 用户设置:
/user/settings
那我们就要对原来的路由结构做一些调整,让这些路径都统一归类到 /user/
下。
js
const routes = [
{
path: '/',
element: <Navigate to="/user/home" />
},
{
path: '/login',
element: <Login />
},
{
path: '/user',
children: [
{
index: true,
element: <Navigate to="home" />
},
{
path: 'home',
element: <UserHome />
},
{
path: 'profile',
element: <UserProfile />
},
{
path: 'settings',
element: <UserSettings />
}
]
}
]
children
里的路径是"子路径",它们会自动继承父路径 /user
。所以当用户访问 /user
时,会自动跳转到 /user/home
。