URL 变了,页面没刷新?一篇讲清楚路由,不绕弯!

189 阅读6分钟

在现代 Web 开发中,路由(Routing) 是一个非常重要的概念。无论是传统的网页开发还是如今流行的单页应用(SPA),路由都扮演着“导航”的角色,决定了用户访问哪个页面、看到什么内容。

本文将从最早开始的 后端路由 讲起,再过渡到我们今天要重点讲解的 前端路由,最后结合示例代码,详细解析如何在 React 中使用 react-router-dom 构建路由系统。


🧭 什么是路由?

可以将“路由”理解为网站的“导航地图”。

当用户访问不同的 URL 地址时,系统需要决定:

  • 应该展示哪个页面?
  • 应该调用哪些接口?
  • 应该执行哪些操作?

这个判断和控制的过程就叫做 路由


🚪 后端路由:服务器决定显示哪个页面

📖 早期网页是怎么工作的?

在互联网发展的早期阶段,网页是由服务器生成并返回给浏览器的。

✅ 工作流程如下:

  1. 用户输入网址:比如 http://example.com/user/123
  2. 浏览器向服务器发起请求
  3. 服务器根据 URL 判断用户想要访问的内容
  4. 服务器生成 HTML 页面并返回
  5. 浏览器收到 HTML 并渲染出来

这就是典型的 后端路由:所有的页面跳转、数据处理、HTML 渲染都是由服务器完成的。


🔁 类比说明

想象在图书馆借书:

  • 每次换一本书都要重新登记一次(相当于每次跳转都要请求服务器)
  • 图书馆前台会给你一本新书(相当于服务器返回新的 HTML 页面)

这就是后端路由的特点:每一次跳转都需要刷新页面


✅ 后端路由的优点:

优点描述
简单直接不依赖 JavaScript,适合小型静态网站
SEO 友好搜索引擎可以轻松抓取完整 HTML 内容
安全性高数据处理都在服务器端进行

❌ 后端路由的缺点:

缺点描述
页面加载慢每次跳转都要重新加载整个页面
用户体验差页面频繁刷新,交互不够流畅
前端参与度低所有逻辑都在后端实现,不利于前后端分离

🌐 前端路由:页面切换不再刷新

随着技术的发展,越来越多的网站采用 单页应用(SPA, Single Page Application) 架构,其中核心就是 前端路由

💡 前端路由是什么?

简单来说,前端路由是通过 JavaScript 控制页面内容的变化,而不需要每次都去请求服务器。

✅ 工作流程如下:

  1. 用户第一次访问 /home,浏览器向服务器请求资源
  2. 服务器只返回一个 index.html 和一些 JS 文件
  3. JS 加载完成后接管页面
  4. 当用户点击“About”按钮时,URL 改为 /about,但页面不会刷新
  5. 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 是必不可少的技能。