Vue3 教學:路由系統(Vue Router 4)— 命名路由與參數
簡介
在單頁應用(SPA)中,路由是連接不同畫面的關鍵機制。Vue Router 4 為 Vue 3 提供了完整且彈性的路由功能,而「命名路由」與「路由參數」則是實務開發中最常使用的兩項技巧。
使用命名路由可以讓我們在程式碼中以易讀的名稱呼叫目標頁面,避免硬編碼 URL;而路由參數(包括路徑參數與查詢參數)則讓同一個畫面可以根據不同資料顯示不同內容,從商品詳情到使用者個人檔案,皆可輕鬆實現。
本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,帶你一步步掌握 Vue Router 4 中的命名路由與參數,讓你的 Vue 3 專案更具可讀性與可維護性。
核心概念
1. 什麼是命名路由?
在 Vue Router 中,每一條路由規則除了 path、component 之外,還可以設定 name 屬性。
{
path: '/user/:id',
name: 'UserDetail', // ← 這裡是命名路由
component: UserDetail
}
有了 name,我們在程式中不必直接寫 '/user/123',而是透過 router.push({ name: 'UserDetail', params: { id: 123 } }) 來導向。這樣的好處包括:
- 解耦:路徑變更時只需更新路由設定,呼叫端不必改動。
- 可讀性:
UserDetail比起'/user/:id'更能表達意圖。 - 支援動態參數:自動把
params轉換成正確的 URL。
2. 路由參數的類型
| 類型 | 說明 | 定義方式 |
|---|---|---|
| 路徑參數(Path Params) | 直接寫在 path 中,用 : 開頭。 |
/product/:productId |
| 查詢參數(Query Params) | 位於 URL ? 後的鍵值對。 |
router.push({ name: 'Search', query: { q: 'vue' } }) |
| 動態段(Optional Params) | 透過正則或 ? 讓參數可省略。 |
/blog/:slug? |
3. 取得參數的方式
在組件內,我們可以透過 useRoute()(Composition API)或 this.$route(Options API)取得。
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
// 路徑參數
const productId = route.params.productId
// 查詢參數
const keyword = route.query.q
return { productId, keyword }
}
}
4. 參數的類型轉換
params 皆為字串,若需要數字或布林值,請自行轉型:
const id = Number(route.params.id) // 轉成 Number
const isAdmin = route.query.admin === 'true' // 轉成 Boolean
程式碼範例
下面提供 5 個實用範例,從最簡單的命名路由到組合查詢與路徑參數,並附上說明。
範例 1:基本的命名路由與路徑參數
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import UserDetail from '@/views/UserDetail.vue'
const routes = [
{
path: '/user/:id',
name: 'UserDetail', // ← 命名路由
component: UserDetail,
props: true // 把 params 直接作為 props 傳入
}
]
export default createRouter({
history: createWebHistory(),
routes
})
<!-- UserDetail.vue -->
<template>
<div>
<h2>使用者 ID:{{ id }}</h2>
</div>
</template>
<script setup>
// 由於在路由設定中 props: true,直接以 prop 取得
defineProps(['id'])
</script>
說明:
router.push({ name: 'UserDetail', params: { id: 42 } })會自動產生/user/42,且id直接以prop形式注入元件。
範例 2:使用查詢參數(Query)
// 另一條路由
{
path: '/search',
name: 'Search',
component: () => import('@/views/Search.vue')
}
<!-- Search.vue -->
<template>
<div>
<h2>搜尋結果:{{ keyword }}</h2>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const keyword = route.query.q || ''
</script>
// 從其他組件導向搜尋頁
router.push({ name: 'Search', query: { q: 'vue router' } })
說明:查詢參數不會影響
path,因此同一條路由可接受任意組合的q。
範例 3:同一畫面支援多種參數(路徑 + 查詢)
{
path: '/article/:slug',
name: 'ArticleDetail',
component: () => import('@/views/ArticleDetail.vue')
}
<!-- ArticleDetail.vue -->
<template>
<div>
<h1>{{ article.title }}</h1>
<p>作者:{{ article.author }}</p>
<p v-if="highlight">🔍 目前在高亮顯示關鍵字:{{ highlight }}</p>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const slug = route.params.slug
const highlight = route.query.highlight // 可選的查詢參數
const article = ref({ title: '', author: '' })
onMounted(async () => {
// 假設有一個 API 會根據 slug 回傳文章資料
const data = await fetch(`/api/articles/${slug}`).then(r => r.json())
article.value = data
})
</script>
說明:使用者可以透過
router.push({ name: 'ArticleDetail', params: { slug: 'vue3-intro' }, query: { highlight: 'Composition API' } })同時帶入路徑參數與查詢參數。
範例 4:動態載入子路由並使用命名視圖
{
path: '/dashboard',
component: () => import('@/layouts/DashboardLayout.vue'),
children: [
{
path: '',
name: 'DashboardHome',
components: {
default: () => import('@/views/DashboardHome.vue'),
sidebar: () => import('@/components/DashboardSidebar.vue')
}
},
{
path: 'settings',
name: 'DashboardSettings',
component: () => import('@/views/DashboardSettings.vue')
}
]
}
// 從任意位置切換到設定頁
router.push({ name: 'DashboardSettings' })
說明:即使有多個子路由,仍可透過 命名路由 直接切換,避免硬編碼
'/dashboard/settings'。
範例 5:利用 props 函式自訂參數型別
{
path: '/order/:orderId',
name: 'OrderDetail',
component: () => import('@/views/OrderDetail.vue'),
// 把字串轉成 Number,並額外帶入 query 作為布林值
props: route => ({
orderId: Number(route.params.orderId),
isAdmin: route.query.admin === 'true'
})
}
<!-- OrderDetail.vue -->
<template>
<div>
<h2>訂單編號:{{ orderId }}</h2>
<p v-if="isAdmin">(管理者模式)</p>
</div>
</template>
<script setup>
defineProps({
orderId: Number,
isAdmin: Boolean
})
</script>
說明:透過
props函式,我們在路由層就完成了型別轉換,元件內部不必再自行Number(),保持乾淨的資料流。
常見陷阱與最佳實踐
| 陷阱 | 原因 | 解決方案 / 最佳實踐 |
|---|---|---|
忘記在路由設定 props: true |
元件只能透過 $route.params 取得參數,導致耦合度高。 |
在需要的路由加上 props: true 或使用 props: route => ({ … }),讓參數直接變成 props。 |
| 硬編碼 URL | 當路徑變更時,需要逐一搜尋替換,易遺漏。 | 統一使用命名路由 (router.push({ name: 'xxx', params: {...} }))。 |
| 路徑參數與查詢參數混用時忘記解碼 | URL 中的特殊字元(如空格)會被編碼,直接顯示會不友善。 | 使用 decodeURIComponent(route.query.xxx),或在後端 API 前先解碼。 |
| 未處理不存在的參數 | 使用 route.params.id 時若未傳入,會得到 undefined,導致錯誤。 |
在組件內加入 預設值 或 驗證(例如 `const id = Number(route.params.id) |
路由守衛中直接 next('/') |
會失去原本的參數資訊,使用者可能被導向錯誤頁面。 | 使用 next({ name: 'Login', query: { redirect: to.fullPath } }),保留原始路徑。 |
最佳實踐
- 統一使用命名路由:所有導向行為(
router-link、router.push、router.replace)皆以name為主。 - 在路由層完成型別轉換:利用
props函式或beforeEnter把字串轉成正確型別,減少元件內的資料清理工作。 - 將參數驗證抽離成可重用的函式:例如
validateId(id),在多個元件或守衛中共用。 - 善用
router.resolve:在需要產生 URL(例如 SEO、分享連結)時,可使用router.resolve({ name: 'Product', params: { id: 7 } }).href。 - 保持路由結構扁平化:過深的巢狀路由會讓參數傳遞變得混亂,盡量在同層路由中使用
name表示子頁面。
實際應用場景
1. 電商商品詳情頁
- 路徑參數:
/product/:productId(商品編號) - 查詢參數:
?ref=campaign2025(來源追蹤) - 使用方式:在列表頁
router.push({ name: 'ProductDetail', params: { productId: item.id }, query: { ref: 'campaign2025' } })。
2. 多語系網站
- 命名路由:
name: 'Home'、name: 'About'等。 - 切換語系:
router.push({ name: to.name, params: to.params, query: { lang: 'en' } }),保持相同路徑,只改變lang查詢參數。
3. 後台管理員介面
- 動態子路由:
/admin/users/:userId、/admin/settings。 - 權限守衛:在
beforeEach檢查to.meta.requiresAdmin,若未授權則next({ name: 'Login', query: { redirect: to.fullPath } })。
4. 文章搜尋與高亮
- 路徑:
/article/:slug - 查詢:
?highlight=Vue用於在文章內自動滾動並標記關鍵字。
5. 動態表單編輯
- 路徑:
/form/:formId/edit - 查詢:
?mode=readonly控制表單是否可編輯。 - 實作:在表單元件內依
route.query.mode判斷 UI 狀態。
總結
- 命名路由是 Vue Router 4 中提升可讀性、降低耦合度的關鍵技巧,建議在專案中盡可能使用。
- 路徑參數與 查詢參數讓同一個畫面可以根據不同資料呈現多樣內容,配合
props轉換與型別驗證,可保持資料流的乾淨與安全。 - 常見的陷阱大多與「硬編碼」、「型別未轉換」或「參數遺失」有關,透過 最佳實踐(統一使用
name、在路由層完成型別轉換、驗證參數)即可有效避免。 - 在實務開發中,從電商商品頁、後台管理、到多語系切換,都能看到命名路由與參數的身影,掌握這兩項技巧,能讓你的 Vue 3 專案在可維護性與擴充性上更上一層樓。
祝你在 Vue 3 的路由世界裡玩得開心,開發出更優雅、更健壯的單頁應用!