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 Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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]] - 嵌套路由的出口 / 占位符