在现代 Web 开发中,路由(Routing) 是一个非常重要的概念。无论是传统的网页开发还是如今流行的单页应用(SPA),路由都扮演着“导航”的角色,决定了用户访问哪个页面、看到什么内容。
本文将从最早开始的 后端路由 讲起,再过渡到我们今天要重点讲解的 前端路由,最后结合示例代码,详细解析如何在 React 中使用 react-router-dom 构建路由系统。
🧭 什么是路由?
可以将“路由”理解为网站的“导航地图”。
当用户访问不同的 URL 地址时,系统需要决定:
- 应该展示哪个页面?
- 应该调用哪些接口?
- 应该执行哪些操作?
这个判断和控制的过程就叫做 路由。
🚪 后端路由:服务器决定显示哪个页面
📖 早期网页是怎么工作的?
在互联网发展的早期阶段,网页是由服务器生成并返回给浏览器的。
✅ 工作流程如下:
- 用户输入网址:比如
http://example.com/user/123 - 浏览器向服务器发起请求
- 服务器根据 URL 判断用户想要访问的内容
- 服务器生成 HTML 页面并返回
- 浏览器收到 HTML 并渲染出来
这就是典型的 后端路由:所有的页面跳转、数据处理、HTML 渲染都是由服务器完成的。
🔁 类比说明
想象在图书馆借书:
- 每次换一本书都要重新登记一次(相当于每次跳转都要请求服务器)
- 图书馆前台会给你一本新书(相当于服务器返回新的 HTML 页面)
这就是后端路由的特点:每一次跳转都需要刷新页面。
✅ 后端路由的优点:
| 优点 | 描述 |
|---|---|
| 简单直接 | 不依赖 JavaScript,适合小型静态网站 |
| SEO 友好 | 搜索引擎可以轻松抓取完整 HTML 内容 |
| 安全性高 | 数据处理都在服务器端进行 |
❌ 后端路由的缺点:
| 缺点 | 描述 |
|---|---|
| 页面加载慢 | 每次跳转都要重新加载整个页面 |
| 用户体验差 | 页面频繁刷新,交互不够流畅 |
| 前端参与度低 | 所有逻辑都在后端实现,不利于前后端分离 |
🌐 前端路由:页面切换不再刷新
随着技术的发展,越来越多的网站采用 单页应用(SPA, Single Page Application) 架构,其中核心就是 前端路由。
💡 前端路由是什么?
简单来说,前端路由是通过 JavaScript 控制页面内容的变化,而不需要每次都去请求服务器。
✅ 工作流程如下:
- 用户第一次访问
/home,浏览器向服务器请求资源 - 服务器只返回一个
index.html和一些 JS 文件 - JS 加载完成后接管页面
- 当用户点击“About”按钮时,URL 改为
/about,但页面不会刷新 - JS 根据当前 URL 动态加载对应组件并更新页面内容
🔄 继续用图书馆的例子来类比:
- 一次性把所有书带回家(JS、CSS、HTML 一次性加载)
- 在家自己翻阅不同书籍(前端切换内容)
- 不用每次都回图书馆前台登记(不频繁请求服务器)
✅ 前端路由的优点:
| 优点 | 描述 |
|---|---|
| 页面切换快 | 无刷新切换,用户体验更流畅 |
| 减少服务器压力 | 只需首次加载资源,后续由前端控制 |
| 更好的交互体验 | 类似 App 的操作感受 |
❌ 前端路由的缺点:
| 缺点 | 描述 |
|---|---|
| 首屏加载较慢 | 需要先下载 JS 文件才能开始渲染 |
| SEO 不友好 | 默认无法被搜索引擎抓取,除非使用 SSR |
| 开发复杂度较高 | 需要掌握前端框架和路由配置知识 |
📚 常见的前端路由实现方式
React 中最常用的路由库是 react-router-dom,它支持两种模式:
1️⃣ Hash 模式(带 # 的 URL)
http://yourdomain.com/#/home
http://yourdomain.com/#/user/123
- 使用
window.location.hash实现 - 不需要服务器配合
- 缺点:URL 不够美观
2️⃣ History 模式(更自然的 URL)
http://yourdomain.com/home
http://yourdomain.com/user/123
- 使用 HTML5 的
history.pushState()API - URL 更干净、更符合 RESTful 规范
- 需要服务器配置支持(如 Nginx 设置 fallback 到
index.html)
!!!想详细了解请看:前端路由的 Hash 模式与 History 模式详解:从原理到实战探索前端路由的奥秘,Hash vs History模 - 掘金
⚙️ React 路由实战:使用 react-router-dom 构建 SPA
以下是一个典型的 React 路由结构:
import {
BrowserRouter as Router,// 前端路由
Routes, // 路由设置容器
Route // 单条路由
} from 'react-router-dom'
import './App.css'
import { Home } from './pages/Home'
import { About } from './pages/About'
import { UserProfile } from './pages/UserProfile'
import { Products } from './pages/Products'
import { ProductDetails } from './pages/Products/ProductDetails'
import { NewProduct } from './pages/Products/NewProduct'
function App() {
return (
<>
{/* 前端路由接管一切,配置 */}
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user/:id" element={<UserProfile />} />
<Route path="/products" element={<Products />}>
{/* 二级路由 */}
<Route path=":productsID" element={<ProductDetails />} />
<Route path="new" element={<NewProduct />} />
</Route>
</Routes>
</Router>
</>
)
}
export default App
📂 关键组件说明:
1. <BrowserRouter> / <Router>
这是整个前端路由的根容器,启用的是 History 模式,意味着你的 URL 看起来像这样:
http://yourdomain.com/about
而不是:
http://yourdomain.com/#/about
在代码中,<BrowserRouter> 被导入并重命名为 <Router>,是为了简化书写,提高可读性。
2. <Routes>
用于包裹多个 <Route>,它是路由匹配的容器。
3. <Route path="..." element={...} />
定义一条路由规则:
path: 匹配的 URL 路径element: 当路径匹配时要显示的组件
4. 嵌套路由 & <Outlet />
可以嵌套路由,例如:
<Route path="/products" element={<Products />}>
<Route path=":productId" element={<ProductDetails />} />
<Route path="new" element={<NewProduct />} />
</Route>
此时,在 Products 组件中必须使用 <Outlet /> 来作为子路由的占位符:
export const Products = () => {
return (
<>
<h1>产品列表</h1>
<Outlet /> {/* 子路由在这里显示 */}
</>
)
}
🧩 获取动态参数:useParams
比如想获取 /user/123 中的 123,可以使用 useParams:
import { useParams } from "react-router-dom"
export const UserProfile = () => {
const { id } = useParams()
return (
<h1>User Profile: {id}</h1>
)
}
🛠 react-router-dom 的版本说明
项目中使用了 react-router-dom@7.6.3,这是一个语义化版本号:
| 版本号 | 含义 |
|---|---|
| 7.x.x | 主版本,可能包含重大变更 |
| x.6.x | 次版本,新增功能,兼容旧版 |
| x.x.3 | 修订号,修复 bug 或安全问题 |
所以:
- 升级到
7.6.4:仅修复 bug,建议升级 - 升级到
7.7.0:新增功能,可选升级 - 升级到
8.0.0:重大变更,需评估是否兼容
📘 总结一下:前端路由 vs 后端路由
| 对比项 | 后端路由 | 前端路由 |
|---|---|---|
| 页面跳转是否刷新 | 是 | 否 |
| 是否请求服务器 | 每次跳转都请求 | 只有首次请求 |
| URL 改变谁负责 | 服务器 | 前端 JavaScript |
| 用户体验 | 较慢 | 更流畅 |
| SEO 友好吗 | 是 | 否(除非使用 SSR) |
| 适合场景 | 传统网站、博客、CMS | 单页应用(SPA)、管理后台、App 页面 |
前端路由是现代 Web 开发的核心之一,特别是使用 React 这样的框架时,掌握
react-router-dom是必不可少的技能。