本文 AI 產出,尚未審核

Vue3 路由系統(Vue Router 4)——router-linkrouter-view 完全攻略


簡介

在單頁應用(SPA)中,頁面切換不再是瀏覽器的完整重新載入,而是透過路由系統在同一個 HTML 入口點內切換不同的組件。Vue3 官方配套的 Vue Router 4 提供了兩個最常使用的全域組件:router-linkrouter-view

  • router-link 負責宣告式的導向(導航),讓使用者點擊時能以宣告式的方式改變 URL 並觸發對應的組件渲染。
  • router-view 則是佔位符,它會根據目前的路由狀態,動態插入對應的組件。

掌握這兩個組件的使用方式與細節,才能寫出結構清晰、可維護且具備 SEO 友好(配合 SSR) 的 Vue3 應用。本篇將從概念說明、實作範例、常見陷阱與最佳實踐,一步步帶你深入了解 router-linkrouter-view 的每個細節。


核心概念

1. router-link:宣告式導航

router-link 本質上是一個 Vue 組件,它會渲染成 <a> 標籤(預設),並自動攔截點擊事件,使用 HTML5 History API(或 hash)改變瀏覽器 URL,而不會觸發頁面重新載入。

1.1 基本使用

<router-link to="/about">關於我們</router-link>
  • to 屬性接受 字串路由定位物件(object),可寫成:
// 物件寫法
<router-link :to="{ name: 'User', params: { id: 123 } }">使用者 123</router-link>

1.2 常用屬性

屬性 說明
to 目標路由(字串或物件)
replace 使用 router.replace(),不會留下瀏覽紀錄(預設 false
active-class 當前路由匹配時套用的自訂 CSS 類名(預設 router-link-active
exact-active-class 完全匹配時套用的類名(預設 router-link-exact-active
custom 以「作用域插槽」的方式自行渲染 <a>,可自訂樣式或包裝元素

1.3 範例:自訂 active-class

<router-link to="/home" active-class="my-active">首頁</router-link>

<style>
.my-active {
  color: #42b983;
  font-weight: bold;
}
</style>

2. router-view:路由組件的渲染容器

router-view 只是一個 佔位符,它會根據目前的路由匹配結果,渲染對應的 路由組件。如果路由設定了巢狀子路由,則子路由的 router-view 會渲染在父組件的 router-view 內部,形成「多層嵌套」的 UI 結構。

2.1 基本使用

<!-- App.vue -->
<template>
  <nav>
    <router-link to="/">首頁</router-link>
    <router-link to="/about">關於</router-link>
  </nav>

  <!-- 這裡會根據路由顯示 Home 或 About 組件 -->
  <router-view />
</template>

2.2 命名視圖(Named Views)

當一個路由需要同時渲染多個視圖時,可使用 name 屬性給 router-view 命名,並在路由設定中指定 components(注意是複數)。

<!-- App.vue -->
<template>
  <header>
    <router-view name="header" />
  </header>

  <main>
    <router-view />
  </main>

  <footer>
    <router-view name="footer" />
  </footer>
</template>
// router/index.js
const routes = [
  {
    path: '/',
    components: {
      default: Home,          // 會渲染到未命名的 <router-view>
      header: MainHeader,
      footer: MainFooter
    }
  },
  // ...
];

2.3 動態路由參數與 props 傳遞

// router/index.js
{
  path: '/user/:id',
  component: UserDetail,
  props: true   // 直接把 route.params 傳給組件的 props
}
<!-- UserDetail.vue -->
<template>
  <div>使用者 ID:{{ id }}</div>
</template>

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

3. 程式碼範例合集

以下提供 5 個實務中常會用到的範例,從最基礎到稍微進階的情境都有涵蓋。


範例 1:基礎導航與路由設定

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

const routes = [
  { path: '/', name: 'Home', component: Home },
  { path: '/about', name: 'About', component: About },
];

export default createRouter({
  history: createWebHistory(),
  routes,
});
<!-- App.vue -->
<template>
  <nav>
    <router-link to="/">🏠 Home</router-link>
    <router-link to="/about">ℹ️ About</router-link>
  </nav>

  <router-view />
</template>

<script setup>
import router from '@/router';
</script>

說明router-link 直接使用字串路徑,router-view 會根據 routes 中的 component 動態渲染。


範例 2:使用路由名稱與參數

<!-- NavBar.vue -->
<template>
  <router-link :to="{ name: 'User', params: { id: userId } }">
    查看使用者 {{ userId }}
  </router-link>
</template>

<script setup>
import { ref } from 'vue';
const userId = ref(42);
</script>
// router/index.js
{
  path: '/user/:id',
  name: 'User',
  component: () => import('@/views/UserDetail.vue'),
  props: true
}

技巧:使用路由名稱 (name) 可以避免因路徑變更而忘記同步 router-link,提升維護性。


範例 3:自訂 active-classexact 匹配

<nav>
  <router-link to="/" exact-active-class="active-exact">首頁</router-link>
  <router-link to="/products" active-class="active">商品列表</router-link>
</nav>

<style>
.active {
  color: #ff6600;
}
.active-exact {
  font-weight: bold;
}
</style>

重點exact 僅在路徑 完全相同 時才套用,適合首頁或根路由的樣式控制。


範例 4:命名視圖(Header / Footer)

<!-- Layout.vue -->
<template>
  <header><router-view name="header" /></header>
  <main><router-view /></main>
  <footer><router-view name="footer" /></footer>
</template>
// router/index.js
{
  path: '/',
  components: {
    default: Home,
    header: MainHeader,
    footer: MainFooter
  }
}

實務:在大型網站(例如電商)常會把「導覽列」與「頁腳」抽成獨立元件,使用命名視圖即可在不同路由間共享或替換。


範例 5:使用 custom 插槽自行渲染連結

<router-link to="/profile" custom v-slot="{ navigate, isActive, href }">
  <button :class="{ active: isActive }" @click="navigate">
    個人檔案
  </button>
</router-link>

<style>
button.active {
  background: #42b983;
  color: #fff;
}
</style>

說明custom 讓你拋棄預設的 <a>,直接用 <button><div> 或任何自訂元素,同時保留路由導航的完整功能(navigateisActive 等)。


常見陷阱與最佳實踐

陷阱 可能的結果 建議的解決方案
忘記在 router-link 加上 :to 的綁定(直接寫 to="/path" 當路徑是變數或計算屬性時,會變成字面字串,導致導航失敗。 使用 :to="computedPath"v-bind:to 方式綁定。
使用相對路徑時產生錯誤 例如在子路由中 to="detail" 會被解析成 /parent/detail,但若預期是 /detail,就會找不到組件。 盡量使用 絕對路徑 (/detail) 或 路由名稱 ({ name: 'Detail' })。
router-view 放錯位置,導致子路由渲染不到 子路由的內容會被渲染到父層的 router-view,或根本不顯示。 確認父組件中已放置 未命名的 router-view,或正確使用 name 屬性對應子路由。
props: true 失效 當組件使用 setup() 且未定義 defineProps 時,路由參數不會自動注入。 <script setup> 中使用 defineProps,或在傳統 export default 中使用 props: ['id']
router-linkreplace 誤用 使用 replace 後,使用者無法利用瀏覽器返回鍵回到前一頁。 只在「跳過歷史紀錄」的情境(如登入成功後直接導向首頁)使用。

最佳實踐

  1. 統一使用路由名稱:在大型專案中,路徑可能會因需求調整而改變,使用 name 可避免每個 router-link 都要同步修改。
  2. 將路由設定拆分模組:例如 routes/auth.jsroutes/dashboard.js,然後在 router/index.js 中匯入,提升可讀性與維護性。
  3. 利用 meta 欄位做權限或佈局控制:在路由定義中加入 meta: { requiresAuth: true, layout: 'admin' },再於全域守衛或 router-view 包裝層判斷。
  4. 懶載入(code‑splitting):使用動態匯入 (import()) 讓每個路由只在需要時才載入,減少首屏載入大小。
  5. router-view 使用 <transition> 包裝:可為路由切換加入過場動畫,提升使用者體驗。
<template>
  <transition name="fade" mode="out-in">
    <router-view />
  </transition>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition: opacity .3s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

實際應用場景

場景 為什麼需要 router-link / router-view 典型實作方式
多層次管理後台 需要在左側選單切換不同子頁面,同時保留主內容區的切換。 左側選單使用 router-link(帶 active-class),右側放置 router-view,子路由再嵌套自己的 router-view
行動端 Tab 切換 Tab 切換本質上是路由切換,讓網址保持同步,允許深層鏈接。 每個 Tab 使用 router-linkrouter-view 放在 <keep-alive> 內部以保留狀態。
動態產品詳情頁 產品 ID 為路由參數,需根據 id 載入對應資料。 router-link 生成 /product/:idrouter-view 渲染 ProductDetail.vueprops: true 直接取得 id
A/B 測試或多語系切換 不同語系或測試變體可能共用同一個路由,僅透過組件切換。 在路由的 meta 中放置語系資訊,router-view 搭配全域守衛或 watch($route) 改變組件內容。
SEO 友好的 SSR 伺服器端需要根據路由渲染完整 HTML。 router-link 仍然產生 <a>router-view 在服務端渲染時會輸出對應的組件 HTML。

總結

router-linkrouter-view 是 Vue Router 4 中最基礎、也最關鍵的兩個全域組件。透過 宣告式router-link,我們可以輕鬆管理 URL 與導航行為;而 router-view 則負責根據路由狀態動態插入對應的組件,支援 命名視圖巢狀子路由懶載入 等進階功能。

在開發過程中,記得:

  • 使用路由名稱 取代硬編碼路徑
  • 妥善設定 active-class 讓導覽列的 UI 更直觀
  • 利用 props: true 直接把路由參數傳給組件,減少耦合
  • 善用命名視圖 讓布局層級更彈性
  • 加入過場動畫懶載入,提升使用者體驗與效能

只要掌握上述概念與最佳實踐,你就能在 Vue3 專案中建立結構清晰、可擴充且易於維護的路由系統,為你的 SPA 打下堅實的基礎。祝開發順利,玩得開心! 🚀