This repository has been archived on 2026-05-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
obsidian/金山办公作业/Week06/路由原理.md
T

114 lines
3.9 KiB
Markdown
Raw Normal View History

2026-04-25 22:15:39 +08:00
---
tags: [frontend, react, react-router, routing, spa]
create time: 2026-04-25 15:30
---
# 路由原理:BrowserRouter 与组件协作
## 概述
本文梳理 React Router 的核心组件如何配合完成单页应用(SPA)的路由跳转。重点理解 `<BrowserRouter>` 作为"路由引擎"的作用,以及 `NavLink`、`Routes`、`Route`、`Navigate` 等组件的职责分工。
---
## 正文
### `<BrowserRouter>` 的核心作用
`<BrowserRouter>` 就是 React Router 的**"总开关"和"运行环境"**,没有它,路由组件无法正常工作。
```tsx
<BrowserRouter>
<App />
</BrowserRouter>
```
它做三件事:
1. **提供路由上下文** — 让 `Routes`、`Route`、`NavLink` 知道当前路径是什么、该显示哪个页面
2. **无刷新切换页面** — 基于浏览器的 `History API`,URL 变了但整页不会刷新
3. **全局可用** — 因为它包住了 `<App />`,其所有子组件都能使用路由能力
> 💡 **想一想**:为什么 `<BrowserRouter>` 必须包裹 `<App />` 而不是只包某个子组件?
>
> 如果它只包了 `<Routes>` 但没有包 `<NavLink>`,点击导航按钮会报错:
>
> ```
> Uncaught Error: useHref() may be used only in the context of a <Router> component
> ```
>
> 因为 `NavLink` 内部通过 React Context 读取路由数据,如果它处于 `<BrowserRouter>` 之外,就**读不到任何路由信息**,只能直接崩溃。
### 组件职责类比
| 组件 | 类比角色 | 一句话说明 |
|------|---------|-----------|
| `<BrowserRouter>` | 交通系统 | 提供整个路由的运行环境 |
| `NavLink` | 路牌 / 入口 | 用户点击后触发路径切换 |
| `Routes` | 调度中心 | 读取当前路径,决定走哪条路 |
| `Route` | 目的地 | 定义"路径 → 页面"的映射 |
| `Navigate` | 自动转弯 | 把用户重定向到另一个路径 |
### 路由流程
当用户点击左侧导航栏的"课程管理"时,背后发生了什么?
```mermaid
flowchart LR
A[用户点击 NavLink] --> B[URL 变为 /courses]
B --> C[Routes 读取当前路径]
C --> D{匹配哪个 Route?}
D -->|path=/courses| E[渲染 CoursesPage]
D -->|无匹配| F[不显示任何页面]
E --> G[页面切换完成,整页未刷新]
```
逐帧拆解:
1. `NavLink to="/courses"` 将浏览器地址变为 `/courses`
2. `Routes` 读取当前路径
3. 匹配到 `<Route path="/courses" element={<CoursesPage />} />`
4. `CoursesPage` 组件渲染
整个过程**地址栏变了、组件切换了、但页面没有刷新**。
### 实际代码中的用法
**路由声明**(`App.tsx`):
```tsx
// 根路径自动跳转到 dashboard(replace 不留后退痕迹)
<Route path="/" element={<Navigate to="/dashboard" replace />} />
// 正常路由映射
<Route path="/dashboard" element={<DashboardPage />} />
<Route path="/courses" element={<CoursesPage />} />
```
**导航链接**:
```tsx
<NavLink to="/courses">课程管理</NavLink>
```
**解读**:`<Route path="/" element={<Navigate to="/dashboard" replace />} />` 表示当用户访问根路径 `/` 时,自动跳转到 `/dashboard`。`replace` 参数会让浏览器用新路径替换当前历史记录,这样用户按"后退"按钮不会回到登录页。
### 为什么不能去掉 `<BrowserRouter>`?
路由组件需要"上下文"才知道当前路径是什么、该往哪里跳。如果去掉 `<BrowserRouter>`:
- `NavLink` 不知道点击后该跳到哪里
- `Route` / `Routes` 不知道当前路径是什么
- `Navigate` 无法执行跳转
它们会直接报错。
> 💡 **想一想**:如果我们不用 `<BrowserRouter>`,还有哪些方式能让路由组件知道当前路径?(提示:URL 地址栏本身就是公开的,React Router 还提供了 `HashRouter` 和 `MemoryRouter`,它们分别适用于什么场景?)
---
## 关联笔记
- [[金山办公作业/Week06/登录安全流程]] - 用户认证与 JWT Token
- [[Outlet]] - 嵌套路由的出口 / 占位符