React 与 React Router:前端路由的演进与实践

105 阅读4分钟

React 与 React Router:前端路由的演进与实践

在现代前端开发中,React 已经成为构建用户界面的核心框架之一。它具有组件化、响应式状态管理、函数式编程风格等优势。然而,React 本身专注于视图层(View Layer),并不直接提供页面之间的导航机制。

这就引出了我们今天要重点探讨的内容:React Router —— React 生态系统中负责实现前端路由的重要工具。

一、什么是路由?为什么需要前端路由?

  1. 前端路由 vs 后端路由

    • 后端路由:主要负责暴露 API 接口资源,处理 HTTP 请求并返回数据(如 JSON)或完整的 HTML 页面。
    • 前端路由:负责在单页应用(SPA)中切换不同的页面级组件,不刷新整个页面,提升用户体验。
  2. 路由的历史演变

    传统 MVC 架构

    早期 Web 开发采用的是后端驱动的方式,用户访问 URL → 后端路由匹配 → 返回完整 HTML 页面(数据嵌套在页面中),每次页面切换都需要一次新的请求和响应。这种模式前后端耦合严重,不利于快速迭代和团队协作。

    7e503ff131d16af5262dd24d672b9db1.png

    现代 MVVM 架构(前后端分离)

    b2bc02bfa2054588bb5e755978380636.webp

    随着技术发展,前后端开始解耦:

    • 后端专注于接口开发(API)
    • 前端通过 fetch 获取数据,渲染页面
    • 前端也引入了路由机制,实现页面间切换

    这就是我们常说的前端路由,而 React 中最常用的实现就是 react-router-dom

二、React 全家桶中的 react-router-dom

**React 本身只负责组件、状态、Hooks 等核心功能。**为了4保持轻量和专注,官方将一些通用功能交由社区维护,比如:

包名功能说明
react核心库:组件、状态、Hooks
react-domDOM 渲染
react-router-dom前端路由支持
redux / mobx状态管理
axios发起网络请求

其中,react-router-dom 是用于 Web 浏览器环境的路由解决方案,目前广泛使用的是 v6 版本。

版本号格式如 7.6.3,其含义如下:

  • 主版本号(7):重大变更
  • 次版本号(6):新增功能但保持兼容
  • 修订号(3):小 bug 修复或优化

三、React 的“特殊”之处:动态路由与 RESTful 设计

动态路由设计

React 支持非常灵活的 URL 定义方式,例如:

<Route path="/user/:id" element={<UserDetail />} />

这里的 :id 就是一个路径参数(params),可以通过 useParams() 钩子获取:

import { useParams } from 'react-router-dom';

function UserDetail() {
  const { id } = useParams();
  return <div>用户ID: {id}</div>;
}

这使得我们可以根据 URL 动态加载不同内容,非常适合像用户详情页、文章页等场景。

RESTful 风格与 URL 设计

RESTful 是一种国际通用的 API 设计规范,强调通过 URL 和 HTTP 方法来操作资源:

方法示例操作说明(以文章为例)
GET/user/123获取用户信息
POST/post创建新文章
PUT/post/456替换整篇文章
PATCH/post/456局部更新文章
DELETE/post/456删除文章

React Router 非常适合配合 RESTful API 使用,前端通过路由定义页面结构,后端则提供数据接口。

四、React Router 的基本用法

  1. 安装

    npm install react-router-dom
    
  2. App.jsx

    import { useState } from "react";
    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 ProductNew from "./pages/Products/ProductNew";
    
    import {
      BrowserRouter as Router, // 前端路由
      Routes, // 路由设置容器
      Route, // 单条路由
      Link,
    } from "react-router-dom";
    import "./App.css";
    
    function App() {
      const [id, setId] = useState("123");
    
      return (
        <>
          {/* 前端路由接管路由 */}
          <Router>
            <nav>
              <Link to="/">首页</Link> <br />
              <Link to="/about">关于</Link> <br />
              <Link to="/user/123">用户</Link> <br />
              <Link to="/products">产品</Link>
            </nav>
    
            {/* 路由设置容器 */}
            <Routes>
              <Route path="/" element={ <Home />} />
              <Route path="/about" element={<About />} />
    
              {/* 动态路由 */}
              <Route path="/user/:id" element={<UserProfile id={id} />} />
    
              <Route path="/products" element={<Products />}>
                {/* 子路由  二级页面 */}
                <Route path=":productId" element={<ProductDetails />} />
                {/* 子路由  二级页面 */}
                <Route path="new" element={<ProductNew />} />
              </Route>
            </Routes>
          </Router>
        </>
      );
    }
    
    export default App;
    
    

    子组件

    在这些组件中,Home为首页,About、UserProfile、Products与Home同级,而ProductDetails、ProductNew是Products的子组件

    // 首页
    export default function Home(){
        // 页面级别组件
        return(
            <>
                <h1>Home</h1>
            </>
        )
    }
    
    
    // About
    export default function About(){
        return (
            <div>
                <h1>About</h1>
            </div>
        )
    }
    
    // 用户详情页
    import { useParams } from "react-router-dom";
    export default function UserProfile() {
      const {id} = useParams(); // 返回路由参数对象
    
      return (
        <>
          <h1>用户详情页</h1>
          <p>用户id: {id}</p>
        </>
      );
    }
    
    
    // 产品
    import { Outlet, Link } from "react-router-dom";
    export default function Products(){
    
        return (
            <>
                <h1>Products</h1>
                <Link to="/products/new">New Product</Link><br />
                <Link to="/products/1">Product Details</Link>
                <Outlet />
            </>
        )
    }
    
    
    export default function ProductDetails(){
    
        return (
            <>
                <h1>产品详情</h1>
            </>
        )
    }
    
    
    export default function ProductNew(){
        return (
            <>
                <h1>新产品</h1>
            </>
        )
    }
    

    效果展示

    reactRouter.gif

五、React Router 的高级特性

  1. 编程式导航(useNavigate)

    import { useNavigate } from 'react-router-dom';
    
    function LoginButton() {
      const navigate = useNavigate();
    
      function handleLogin() {
        // 登录成功后跳转
        navigate('/dashboard');
      }
    
      return <button onClick={handleLogin}>登录</button>;
    }
    
  2. 懒加载 + 代码分割

    const LazyDashboard = React.lazy(() => import('./pages/Dashboard'));
    
    <Route path="/dashboard" element={
      <React.Suspense fallback="加载中...">
        <LazyDashboard />
      </React.Suspense>
    } />
    
  3. 404 页面处理

    <Route path="*" element={<NotFound />} />