本文 AI 產出,尚未審核

Vue3 路由系統(Vue Router 4)

主題:定義 routes 陣列


簡介

在單頁應用(SPA)中,路由是連結不同畫面、管理 URL 與組件之間關係的核心機制。Vue 3 搭配 Vue Router 4,提供了直覺且彈性的 API,讓開發者只需要在一個 routes 陣列裡描述「路徑 ↔ 組件」的對應,即可完成整個導覽流程。

正確地設計 routes 陣列,不僅能提升程式可讀性、維護性,還能避免常見的 404 錯誤、路由守衛失效懶載入失敗 等問題。本文將從概念說明、實作範例、常見陷阱與最佳實踐,帶你一步步掌握 Vue Router 4 中 routes 陣列的寫法與應用。


核心概念

1. routes 陣列的基本結構

routes 是一個 JavaScript 陣列,每個元素都是一個路由紀錄(route record),最常見的屬性包括:

屬性 型別 說明
path string URL 匹配字串,必填。
component Component path 對應的 Vue 組件,必填。
name string 路由的命名,可在程式碼中以名稱跳轉。
meta object 自訂資料,常用於權限、標題等。
children Array 子路由,形成巢狀結構。
redirect `string object`
alias `string Array`
props `boolean object

重點path 必須以「/」開頭,且同一層級不可有重複路徑,否則匹配結果會不確定。

2. 最簡單的範例

// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import AboutView from '@/views/AboutView.vue'

const routes = [
  { path: '/',          component: HomeView, name: 'home' },
  { path: '/about',     component: AboutView, name: 'about' }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

HomeViewAboutView 直接對應到根路徑與 /about,透過 router-link 即可在畫面間切換。

3. 命名路由與程式碼跳轉

// 在組件內部使用
this.$router.push({ name: 'about' })

使用 命名路由 可以避免硬編碼 URL,當路徑變更時只需要在 routes 陣列裡調整 path,程式碼不需要變動。

4. 巢狀路由(Nested Routes)

import UserLayout from '@/layouts/UserLayout.vue'
import UserProfile from '@/views/user/Profile.vue'
import UserSettings from '@/views/user/Settings.vue'

const routes = [
  {
    path: '/user',
    component: UserLayout,
    children: [
      { path: '',          component: UserProfile, name: 'user-profile' },   // /user
      { path: 'settings', component: UserSettings, name: 'user-settings' } // /user/settings
    ]
  }
]
  • UserLayout 會渲染 <router-view>,其內部再根據子路由顯示不同的子畫面。
  • 子路由的 path 不需要 以「/」開頭,會自動拼接父層路徑。

5. 懶載入(Lazy‑Loading)與代碼分割

在大型專案中,按需載入 可以顯著減少首屏載入時間。Vue Router 4 支援原生的動態 import()

const routes = [
  {
    path: '/dashboard',
    name: 'dashboard',
    component: () => import('@/views/Dashboard.vue')   // <-- 懶載入
  },
  {
    path: '/reports',
    name: 'reports',
    component: () => import('@/views/Reports.vue')
  }
]

Webpack(或 Vite)會自動將每個懶載入的組件拆分成獨立的 chunk,只有在路由被訪問時才會下載。

6. meta 欄位的實務運用

meta 常被用來存放 權限資訊、頁面標題、breadcrumb 等自訂屬性,配合全域守衛(navigation guard)即可實現權限驗證或動態改變 <title>

const routes = [
  {
    path: '/admin',
    component: () => import('@/views/Admin.vue'),
    meta: { requiresAuth: true, title: '管理後台' }
  },
  {
    path: '/login',
    component: () => import('@/views/Login.vue'),
    meta: { guestOnly: true }
  }
]

// 全域前置守衛範例
router.beforeEach((to, from, next) => {
  const isLoggedIn = !!localStorage.getItem('token')
  if (to.meta.requiresAuth && !isLoggedIn) {
    return next({ name: 'login' })
  }
  if (to.meta.guestOnly && isLoggedIn) {
    return next({ name: 'home' })
  }
  document.title = to.meta.title || 'Vue App'
  next()
})

7. 參數路由與 props 傳遞

// routes
{
  path: '/product/:id',
  name: 'product-detail',
  component: () => import('@/views/ProductDetail.vue'),
  props: true           // 直接把 route.params 轉成 props
}
<!-- ProductDetail.vue -->
<template>
  <div>商品編號:{{ id }}</div>
</template>

<script setup>
defineProps(['id'])
</script>

使用 props: true 可以讓組件 更易於單元測試,因為它不必依賴 $route

8. 重新導向(Redirect)與別名(Alias)

// 重新導向:舊網址導向新網址
{ path: '/old-home', redirect: '/' },

// 別名:同一組件有多個入口 URL
{ path: '/help', alias: '/support', component: HelpView }

redirect 會改變瀏覽器的 URL,而 alias 則保持原 URL,只是渲染同一個組件,適合 SEO 或舊系統兼容。


常見陷阱與最佳實踐

陷阱 說明 解決方式
路徑重複 同層級出現相同 path 會導致匹配衝突。 namealias 區分,或調整層級結構。
忘記在父層加入 <router-view> 子路由不會被渲染。 確認父組件內有 <router-view />
懶載入路徑錯誤 import() 路徑寫錯會導致 404。 使用絕對別名 @/ 或相對路徑,並在 IDE 中確認。
props 未設定 需要路由參數時仍透過 $route.params,降低可測試性。 盡量使用 props: true 或自訂函式返回 props。
全域守衛忘記 next() 導航卡住,畫面不會變更。 確保每條分支都有 next()return next(...)
Meta 資料過度耦合 把太多業務邏輯塞入 meta 只放與路由相關的資訊(如權限、標題),其他邏輯放在 store 或 composable。

最佳實踐

  1. 統一管理:將所有路由定義放在 src/router/index.js,或分模組(module)管理,最後在 createRouter 時合併。
  2. 使用命名路由:避免硬編碼 URL,提升重構彈性。
  3. 懶載入 + Code Splitting:對於非首屏頁面一定使用懶載入。
  4. 保持路由平坦:除非真的需要巢狀 UI,否則盡量避免過深的子路由,減少維護成本。
  5. meta 中加入 title,配合全域守衛自動更新 <title>,提升使用者體驗與 SEO。

實際應用場景

1. 電商平台的商品頁面

  • 需求:商品列表、商品細節、搜尋結果皆需 SEO 友善的 URL。
  • 實作:使用動態參數 /:category/:id,並在 meta.title 中加入商品名稱。
{
  path: '/:category/:id',
  name: 'product',
  component: () => import('@/views/Product.vue'),
  props: route => ({ id: route.params.id, category: route.params.category }),
  meta: { title: route => `商品 - ${route.params.id}` }
}

2. 企業內部系統的權限控管

  • 需求:不同角色只能進入特定功能。
  • 實作:在 meta 加入 roles: ['admin', 'editor'],全域守衛根據使用者角色決定是否允許。
{
  path: '/admin/users',
  component: () => import('@/views/AdminUsers.vue'),
  meta: { requiresAuth: true, roles: ['admin'] }
}

3. 多語系網站的別名路由

  • 需求:同一頁面有中文與英文 URL。
  • 實作:利用 alias 為每個語系提供別名。
{
  path: '/about',
  alias: ['/about-zh', '/about-en'],
  component: AboutView,
  meta: { title: 'About Us' }
}

4. 大型 Dashboard 的懶載入

  • 需求:首屏僅載入概覽,其餘圖表與報表在點擊時才下載。
  • 實作:將每個子頁面設為懶載入,並配合 webpackChunkName 自訂 chunk 名稱。
{
  path: '/dashboard/analytics',
  name: 'analytics',
  component: () => import(/* webpackChunkName: "dashboard-analytics" */ '@/views/Analytics.vue')
}

總結

  • routes 陣列是 Vue Router 4 的靈魂,透過 pathcomponentnamemetachildren 等屬性,我們可以清晰地描述應用程式的導覽結構。
  • 懶載入、命名路由、meta 資料是提升效能與可維護性的關鍵技巧。
  • 常見的陷阱(路徑衝突、忘記 <router-view>、懶載入路徑錯誤)只要遵守 最佳實踐——統一管理、使用命名、保持路由平坦——就能有效避免。
  • 在實務開發中,根據 權限控管、SEO、代碼分割 等需求靈活運用 redirectaliasprops 以及全域守衛,能讓路由系統不僅功能完整,也更具彈性與可測試性。

掌握了 routes 陣列的寫法與最佳實踐,你就能在 Vue3 專案中建立一個 結構清晰、效能優秀、易於維護 的路由系統,為之後的功能擴充與團隊協作奠定穩固基礎。祝開發順利! 🚀