# 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 (
Header
{/* 子路由渲染位置 */}
Footer
); } // 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)