Route 路由:前端世界的“高德地图”,别再用 `<a>` 当导航了!

61 阅读5分钟

你有没有过这种体验?

点了个“个人中心”,页面“唰”一下白屏三秒,表单清空、滚动条归零、连你刚选的优惠券都飞了……你盯着屏幕,内心咆哮:“这网站是用 <a href="xxx.html"> 写的 SPA 吗?!”

朋友,这不是你的错——这是没用好路由(Route) 的锅!😭

今天,我们就来聊聊前端开发中那个“看不见但无处不在”的神器:路由系统。它不是导航栏,也不是菜单,而是你整个单页应用(SPA)的“交通指挥官”+“GPS导航”+“门禁保安”三位一体的存在。

准备好了吗?系好安全带,咱们出发!🚗💨


一、路由是啥?能干嘛?

先说人话版定义:

路由 = 根据 URL 显示不同内容,但不刷新整个页面。

想象一下:你逛淘宝,从“女装”切到“男装”,页面只换中间的商品区,顶部搜索栏、购物车图标、用户头像全都纹丝不动——这就是路由在背后默默干活。

而如果你用的是传统多页应用(MPA),那每次切换都要重新加载整个 HTML,就像每次去超市都得先回家换鞋再出门……累不累啊?👟

所以,现代前端框架(Vue、React、Angular)几乎都离不开路由。没有它,你的 SPA 就是个“假单页”——表面光鲜,内里刷新。

🤖 补充一句:路由 ≠ 导航栏!导航栏只是 UI 按钮,路由才是背后的逻辑大脑。别把按钮当司机!


二、前端路由的两种流派:Hash vs History(井号党 vs 优雅派)

前端路由主要有两种实现方式,它们的区别,堪比“骑共享单车”和“开特斯拉”——都能到目的地,但一个满头大汗,一个空调音乐配咖啡。

1. Hash 模式:URL 里的“#井号青年”

URL 长这样:

https://shop.com/#/cart
https://shop.com/#/order/123

那个 # 后面的部分叫 hash。它的神奇之处在于:改 hash 不会触发页面刷新,也不会向服务器发请求。前端通过监听 window.onhashchange,就能知道用户想去哪,然后换组件。

✅ 优点:兼容性极强,IE8 都能跑(虽然现在 IE 已经进博物馆了)。
❌ 缺点:URL 丑、SEO 差、看起来像临时方案。

😅 真实场景:老板说“先上线再说”,你就用 Hash;老板说“我们要做品牌官网”,赶紧切 History!

2. History 模式:干净清爽的“原生感”

URL 长这样:

https://shop.com/cart
https://shop.com/order/123

是不是瞬间高级了?这靠的是 HTML5 的 history.pushState()popstate 事件。你可以自由修改 URL,浏览器不会刷新,用户体验丝滑如德芙。

但!有个致命坑:如果你直接在地址栏输入 /order/123 并回车,服务器会以为你要一个真实文件,结果返回 404

解决办法?让服务器“兜底”——所有未知路径都返回 index.html

比如 Nginx 配置:

location / {
  try_files $uri $uri/ /index.html;
}

Apache、Node.js、云函数……都有对应配置。记住:前端 History 模式 + 后端兜底 = 完美组合

💡 小贴士:Vue CLI / Vite / Create React App 默认都帮你配好了开发服务器的 fallback,但上线时别忘了配生产环境!


三、实战演练:Vue Router vs React Router,谁更香?

光说不练假把式,上代码!

🍵 Vue Router:官方亲儿子,稳如老狗

安装(Vue 3):

npm install vue-router@4

配置路由:

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import Profile from '@/views/Profile.vue'

const routes = [
  { path: '/', name: 'Home', component: Home },
  { path: '/profile/:id', name: 'Profile', component: Profile }
]

const router = createRouter({
  history: createWebHistory(), // 想用 Hash?换成 createWebHashHistory()
  routes
})

export default router

挂载到 App:

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

模板中使用:

<template>
  <nav>
    <!-- 别用 <a>!用 router-link -->
    <router-link to="/">首页</router-link> |
    <router-link :to="{ name: 'Profile', params: { id: 123 } }">
      我的主页
    </router-link>
  </nav>

  <!-- 这里就是“内容插槽” -->
  <router-view />
</template>

🚨 重点:<router-link> 默认渲染为 <a>,但点击时不会跳转页面,而是触发前端路由切换——这才是 SPA 的灵魂!

☕ React Router:社区扛把子,v6 大改命

安装:

npm install react-router-dom

配置路由(v6+):

// App.jsx
import { BrowserRouter, Routes, Route, Link, useParams } from 'react-router-dom'
import Home from './pages/Home'
import Profile from './pages/Profile'

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">首页</Link> |
        <Link to="/profile/123">我的主页</Link>
      </nav>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/profile/:id" element={<Profile />} />
      </Routes>
    </BrowserRouter>
  )
}

// Profile.jsx
export default function Profile() {
  const { id } = useParams() // 获取动态参数
  return <h1>用户ID:{id}</h1>
}

⚠️ 注意:React Router v6 移除了 <Switch> ,改用 <Routes>;也不再用 component,而是用 element={<Component />}。别被旧教程坑了!


四、进阶玩法:路由还能这么玩?

🔑 1. 动态路由:参数化路径

比如用户详情页 /user/456,其中 456 是动态 ID。

  • Vue:path: '/user/:id' → this.$route.params.id(Options API)或 useRoute().params.id(Composition API)
  • React:path="/user/:id" → const { id } = useParams()

🧩 2. 嵌套路由:页面套娃术

比如 /dashboard/settings/profile,三层结构。

  • Vue:用 children 配置子路由,父组件里放 <router-view>
  • React:在 <Route> 里嵌套 <Routes>,父组件也放 <Outlet />(v6 新增)

🛃 3. 路由守卫:前端的“安检门”

  • 全局前置守卫:登录验证、权限检查

    // Vue
    router.beforeEach((to, from) => {
      if (to.meta.requiresAuth && !isLogin) {
        return '/login'
      }
    })
    
  • 组件内守卫:离开前确认是否保存草稿(Vue 特有)

  • React 方案:用自定义组件包裹,比如 <PrivateRoute>,内部判断权限再渲染

🚀 4. 路由懒加载:提速首屏

别一股脑把所有组件打包进去!按需加载才香:

// Vue
{ path: '/admin', component: () => import('@/views/Admin.vue') }

// React
const Admin = lazy(() => import('./pages/Admin'))
<Route path="/admin" element={<Suspense><Admin /></Suspense>} />

五、避坑指南:这些雷千万别踩!

❌ 坑1:用 query 传大量数据

/user?name=张三&age=25&city=北京&hobby=写bug&avatar=xxx.jpg...

兄弟,这是 URL 还是简历?参数太多不仅丑,还可能超长被截断。用状态管理(Pinia/Vuex/Redux/Zustand)不香吗?

❌ 坑2:忽略 404 页面

用户手输个 /asdfghjkl,结果白屏?赶紧配个兜底路由:

// Vue
{ path: '/:pathMatch(.*)*', component: NotFound }

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

❌ 坑3:History 模式上线后 404

再次强调:前端用 History,后端必须配 fallback!否则用户刷新页面就 GG。


六、结语:路由虽小,乾坤很大

Route 路由,看似只是“换个组件”,实则决定了你 SPA 的流畅度、可维护性和用户体验。

它像空气——平时感觉不到,一旦没了,立马窒息。💨

所以,下次写项目时,请对路由多一分尊重,少一分 <a href> 的冲动。毕竟,用户不想每次点链接都“重生”一次。

✨ 最后送你一句真理:好的路由,让用户忘了“跳转”这件事——他们只记得你的产品丝滑如初恋。