🧭 React Router Dom:前端导航的魔法地图与探险指南

103 阅读7分钟

今天的学习之旅就像一场奇幻的冒险!React Router Dom 就是我的魔法地图,让单页面应用(SPA)变成了充满神秘房间的城堡。让我们点亮火把,开始探索这个奇妙世界吧!

🌍 前端路由 vs 后端路由:地图制造者之争

想象一下你在玩《塞尔达传说》:

  • 后端路由像每次进新房间都要找NPC重新要地图——每次点击链接,服务器就给你一张全新地图(完整HTML页面)。虽然简单直接,但每次加载都要重新画整张地图,林克跑得气喘吁吁。
// 传统后端路由:每次请求返回完整页面
app.get('/about', (req, res) => res.sendFile('about.html'))
  • 前端路由则像获得了希卡之石——首次加载拿到万能地图(JS bundle),之后只需魔法传送(JS动态渲染)。React Router Dom 就是这块神奇的石头!
// 前端路由:只更新局部内容
<Route path="/about" element={<About/>} />

为什么选择前端路由?因为:

  1. 闪电侠速度:页面切换如德芙般丝滑
  2. 省流量冠军:只需传输数据而非重复加载框架
  3. 前后端分离:前端工程师终于不用跪求后端改路由了!🎉

MVC (Model-View-Controller)

  1. 分层结构

    • Model(模型) :负责管理应用程序的数据逻辑,即业务逻辑和数据访问。
    • View(视图) :显示数据给用户,并发送用户的命令到控制器。
    • Controller(控制器) :接收输入并转换它为命令发送给模型或视图。
  2. 工作流程

    • 用户与View交互,触发事件后传递给Controller。
    • Controller处理这些事件,可能调用Model进行数据更新。
    • Model一旦更新完成,通知View进行相应的UI更新。
  3. 特点

    • 强调将数据管理和UI分离。
    • 控制器作为中间人协调模型和视图之间的通信。
    • 更适合传统的服务器端应用开发。

MVVM (Model-View-ViewModel)

  1. 分层结构

    • Model(模型) :与MVC中的模型类似,代表数据和业务逻辑。
    • View(视图) :展示数据并与用户交互,但不直接与Model交互。
    • ViewModel(视图模型) :作为视图的抽象,通过数据绑定机制连接Model和View。它包含视图所需要的所有属性和逻辑,并能响应视图的变化以及更新模型。
  2. 工作流程

    • ViewModel通过观察者模式监听Model的变化,并在自身状态改变时自动更新View。
    • View也可以通过数据绑定直接反映ViewModel的状态变化,无需手动更新。
  3. 特点

    • 数据绑定是核心,减少了大量手动更新UI的代码。
    • 视图和模型之间没有直接联系,全部通过ViewModel进行交互。
    • 更加适合现代的客户端应用,特别是那些需要动态更新UI的应用,如单页应用(SPA)。
  • 后端路由

    早期只有后端路由 server -> 启动http -> 路由(后端) -> 响应html网页 传统的后端驱动的web 开发方式 展示下一个页面 再来一个请求 / /about

    • 优点是足够简单
    • 前后端耦合 后端要写前端的页面
    • 浪费沟通时间
    • 逻辑,数据库,套页面 MVC 开发方式 Model(数据) View(视图) Controller(控制器)
    • 不再以返回页面为主
    • /api/user/123 接口 返回 JSON 数据
  • 前后端分离

    MVVM Model(fetch api) View(JSX) ViewModel(视图模型层 useState,数据绑定JSX)

    • 前后端联调 api开发文档, 约定
    • 前后端分离开发,以API开发文档为约定
    • 前端当家作主
    • 前端也有了路由 react-router-dom /user/:id path 页面级别组件
    • html/css/js react 框架 useState useEffect fetch 请求后端 api接口, 拿到数据 完成web 应用 PC/Mobile/App/小程序/桌面端 大前端

🧙 安装魔法卷轴:初始化仪式

安装咒语简单得像在霍格沃茨点餐:

pnpm install react-router-dom

然后在主神殿(App.jsx)召唤三大守护神:

import { 
  BrowserRouter as Router, // 魔法传送门
  Routes,                  // 路线图容器
  Route                    // 单条探险路径
} from 'react-router-dom'

就像哈利需要9¾站台才能进入魔法世界,整个应用必须包裹在<Router>中:

function App() {
  return (
    <Router> {/* 开启魔法结界 */}
      <Routes> {/* 路线图在此展开 */}
        <Route path="/" element={<Home/>} />
        ...
      </Routes>
    </Router>
  )
}

🗺️ 绘制探险地图:路由配置艺术

一级路径:主城街道

<Route path="/" element={<Home />} />          // 中央广场
<Route path="/about" element={<About />} />     // 情报屋
<Route path="/user/:id" element={<UserProfile />} /> // 居民档案室

这里的:id就像万能钥匙孔——匹配任意用户ID。访问/user/123时,会神奇地变成:

const UserProfile = () => {
    const { id } = useParams();
    useEffect(() => {
        console.log(window.location);
    }, [])
    return (
        <>
            UserProfile {id}

        </>
    )
}

这里作一个简单的演示,我们在URL的ID值会通过useParams()获取 6.gif

嵌套路由:房间中的密室

产品商店里藏着更多房间:

<Route path="/products" element={<Products />}>
  <Route path=":productId" element={<ProductDetails />} /> // 商品详情暗室
  <Route path="new" element={<NewProduct />} />            // 新品铸造室
</Route>

这相当于:

/products             → 商店大门
/products/new         → 新品展示台
/products/fortnite    → 堡垒之夜专柜

🧩 神秘占位符:Outlet组件

在Products组件中,这个神奇标记,就像一个占位符,当我们进入二级路由URL,二级路由的内容会显示在占位符的位置

import { Outlet } from "react-router-dom"

function Products() {
  return (
    <>
      <h1>产品列表</h1>
      <Outlet /> {/* 二级路由在此显形! */}
    </>
  )
}

<Outlet>就像哆啦A梦的任意门:

  • 当访问/products → 显示空白门框
  • 访问/products/new → 门后出现<NewProduct>房间
  • 访问/products/123 → 门后展示<ProductDetails>

可能这么说大家不理解,我们就以掘金为例,我们进入二级路由整个页面时不会变化的,只有占位符的位置会显示不同二级路由的内容:

7.gif

🕵️ 获取探险线索:路由参数解析

在UserProfile组件中,我们使用侦探工具包:

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

function UserProfile() {
  const { id } = useParams() // 提取URL中的ID
  
  return <div>正在查看用户 {id} 的档案</div>
}

useParams()就像福尔摩斯的放大镜:

  1. 当URL是/user/elonmusk → 放大镜显示{ id: 'elonmusk' }
  2. 当URL是/user/007 → 放大镜显示{ id: '007' }

还可以用useEffect监听路径变化:

useEffect(() => {
  console.log(`侦探发现新目标:${id}`)
}, [id]) // id变化时触发

🔗 导航的正确姿势:超链接陷阱

在Home组件中,我发现了危险操作:

// 危险!会导致页面刷新
<a href="http://localhost:5173/about">About</a>

这就像用炸药开门——虽然能到达目的地,但会把整个城堡(SPA体验)炸毁!正确方式是使用React Router的<Link>

import { Link } from 'react-router-dom'

<Link to="/about">About</Link> // 丝滑的密道传送

这里我们用的时超链接,可以很明显的感受到页面的刷新:

8.gif

为什么重要?

方式效果用户体验
<a href>整页刷新,重置所有状态像被踢出城堡
<Link to>局部更新,保持应用状态穿墙术

🧭 RESTful风格路由:冒险者公约

React Router完美支持RESTful规范,就像奇幻世界的通用语言:

// 符合RESTful的路由设计
<Route path="/posts" element={<PostList />}>
  <Route path="new" element={<NewPost />} />      // POST 创建
  <Route path=":id" element={<PostDetail />} />   // GET 读取
  <Route path=":id/edit" element={<EditPost />} />// PATCH 更新
</Route>

HTTP方法与路由的默契配合:

方法路径作用好比...
GET/posts获取文章列表查看任务公告栏
POST/posts创建新文章张贴新悬赏令
GET/posts/:id获取单篇文章阅读特定任务详情
PATCH/posts/:id更新文章修改任务描述
DELETE/posts/:id删除文章撕下过期悬赏令

🌟 终极启示录:路由哲学

经过今天的探险,我领悟到:

  1. 组件即王国
    每个Route对应一个自治领地,通过Props传递信息
  2. URL即坐标
    像地理坐标一样精确描述应用状态:
    https://app.com/products/tech?sort=price#reviews
  3. 路由即叙事
    精心设计的路由如同故事线:
    /welcome → /products → /cart → /checkout
  4. 嵌套即套娃
    路由层级反映UI层级,像俄罗斯套娃般严丝合缝

当夕阳的余晖洒在代码编辑器上,我合上魔法书感叹:React Router Dom 就像一本会自我重写的魔法地图。它不直接创造内容,而是定义了内容呈现的时空规则——何时何地展示何种组件。