# 03-React Router路由与导航
## 📋 学习目标
- 掌握React Router v6核心概念
- 学习路由配置和导航
- 理解路由守卫和权限控制
- 掌握代码分割和懒加载
## 🛣️ React Router基础
### 安装
```bash
pnpm add react-router-dom
```
### 基本配置
```jsx
import {BrowserRouter, Routes, Route, Link} from 'react-router-dom';
function App() {
return (
} />
} />
} />
} />
);
}
```
### 路由模式
```jsx
// BrowserRouter - HTML5 History API
import {BrowserRouter} from 'react-router-dom';
// URL: /about
// HashRouter - Hash模式
import {HashRouter} from 'react-router-dom';
// URL: /#/about
// MemoryRouter - 内存模式(测试用)
import {MemoryRouter} from 'react-router-dom';
```
## 🔗 导航
### Link组件
```jsx
import {Link, NavLink} from 'react-router-dom';
function Navigation() {
return (
);
}
```
### 编程式导航
```jsx
import {useNavigate} from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
await login();
// 导航到首页
navigate('/');
// 带参数导航
navigate('/profile', {state: {from: 'login'}});
// 替换当前历史记录
navigate('/home', {replace: true});
// 后退
navigate(-1);
// 前进
navigate(1);
};
return
;
}
```
## 📍 动态路由
### 路径参数
```jsx
// 路由配置
} />
} />
// 组件中获取参数
import {useParams} from 'react-router-dom';
function UserDetail() {
const {id} = useParams();
return User ID: {id}
;
}
function Comment() {
const {postId, commentId} = useParams();
return (
Post: {postId}, Comment: {commentId}
);
}
```
### 查询参数
```jsx
import {useSearchParams} from 'react-router-dom';
function SearchPage() {
const [searchParams, setSearchParams] = useSearchParams();
// 获取参数
const query = searchParams.get('q');
const page = searchParams.get('page') || '1';
// 设置参数
const handleSearch = (newQuery) => {
setSearchParams({q: newQuery, page: '1'});
};
const nextPage = () => {
setSearchParams({
q: query,
page: String(Number(page) + 1)
});
};
return (
Search: {query}, Page: {page}
);
}
// URL: /search?q=react&page=2
```
## 🗂️ 嵌套路由
### 基本嵌套
```jsx
}>
} />
} />
}>
} />
} />
} />
// Layout组件
import {Outlet} from 'react-router-dom';
function Layout() {
return (
{/* 子路由渲染位置 */}
);
}
// Users组件
function Users() {
return (
Users
{/* UserList或UserDetail渲染这里 */}
);
}
```
### 相对路径
```jsx
function Users() {
return (
);
}
```
## 🔐 路由守卫
### 受保护路由
```jsx
import {Navigate, useLocation} from 'react-router-dom';
function PrivateRoute({children}) {
const isAuthenticated = useAuth();
const location = useLocation();
if (!isAuthenticated) {
// 跳转到登录,保存当前位置
return ;
}
return children;
}
// 使用
} />
}
/>
// 或者使用Layout包裹
}>
} />
} />
```
### 角色权限控制
```jsx
function RoleRoute({children, allowedRoles}) {
const {user} = useAuth();
const location = useLocation();
if (!user) {
return ;
}
if (!allowedRoles.includes(user.role)) {
return ;
}
return children;
}
// 使用
}
/>
```
## ⚡ 代码分割
### 路由级懒加载
```jsx
import {lazy, Suspense} from 'react';
import {Routes, Route} from 'react-router-dom';
// 懒加载组件
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Users = lazy(() => import('./pages/Users'));
function App() {
return (
}>
} />
} />
} />
);
}
// Loading组件
function Loading() {
return Loading...
;
}
```
### 预加载
```jsx
import {lazy} from 'react';
const About = lazy(() => import('./pages/About'));
function Navigation() {
// 鼠标悬停时预加载
const handleMouseEnter = () => {
import('./pages/About');
};
return (
About
);
}
```
## 🔄 数据加载
### Loader(React Router v6.4+)
```jsx
import {createBrowserRouter, RouterProvider, useLoaderData} from 'react-router-dom';
// 定义loader
async function userLoader({params}) {
const response = await fetch(`/api/users/${params.id}`);
if (!response.ok) {
throw new Response('Not Found', {status: 404});
}
return response.json();
}
// 创建路由
const router = createBrowserRouter([
{
path: '/users/:id',
element: ,
loader: userLoader,
errorElement:
}
]);
// 组件中使用
function UserDetail() {
const user = useLoaderData();
return {user.name}
;
}
// App
function App() {
return ;
}
```
### Action(表单处理)
```jsx
async function createUserAction({request}) {
const formData = await request.formData();
const user = {
name: formData.get('name'),
email: formData.get('email')
};
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(user)
});
return redirect('/users');
}
const router = createBrowserRouter([
{
path: '/users/new',
element: ,
action: createUserAction
}
]);
// 组件中使用
import {Form} from 'react-router-dom';
function NewUser() {
return (
);
}
```
## 🎯 实战案例
### 完整的路由配置
```jsx
import {createBrowserRouter, RouterProvider} from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: ,
errorElement: ,
children: [
{
index: true,
element:
},
{
path: 'about',
element:
},
{
path: 'users',
children: [
{
index: true,
element: ,
loader: usersLoader
},
{
path: ':id',
element: ,
loader: userLoader
},
{
path: 'new',
element: ,
action: createUserAction
},
{
path: ':id/edit',
element: ,
loader: userLoader,
action: updateUserAction
}
]
},
{
path: 'dashboard',
element: (
)
}
]
}
]);
function App() {
return ;
}
```
## 💡 最佳实践
### 1. 路由配置集中管理
```jsx
// routes.jsx
export const routes = [
{path: '/', element: },
{path: '/about', element: },
{path: '/users/:id', element: }
];
// App.jsx
import {routes} from './routes';
function App() {
return (
{routes.map(route => (
))}
);
}
```
### 2. 404处理
```jsx
} />
} />
} />
```
### 3. 面包屑导航
```jsx
import {useMatches} from 'react-router-dom';
function Breadcrumbs() {
const matches = useMatches();
return (
);
}
```
## 📚 实践练习
### 练习1:博客系统路由
实现以下路由:
- 文章列表:`/posts`
- 文章详情:`/posts/:id`
- 新建文章:`/posts/new`
- 编辑文章:`/posts/:id/edit`
### 练习2:权限管理
实现:
- 登录保护
- 角色权限控制
- 未授权页面
### 练习3:嵌套布局
实现:
- 多层嵌套路由
- 共享布局
- 面包屑导航
## 📚 参考资料
- [React Router官方文档](https://reactrouter.com/)
- [React Router v6迁移指南](https://reactrouter.com/en/main/upgrading/v5)