Skip to content

Vue Router 巢狀路由:打造高效的頁面版面配置與局部切換機制

在開發複雜的網頁應用時,我們經常會遇到「頁面外殼不變,僅局部內容切換」的需求,例如會員中心、後台管理系統。這時 巢狀路由 (Nested Routes) 就是您的最佳工具。

為什麼需要巢狀路由?

巢狀路由允許我們在父路由元件內部定義子路由,並在特定位置渲染子頁面。

  • 程式碼複用:不需要在每個子頁面重複撰寫相同的導覽列、側邊欄或頁尾。
  • 狀態保持:切換子路由,例如:從「個人資料」切換到「訂單列表」)時,父元件(外殼)不會被銷毀重洗,能保持原有的輸入狀態或滾動位置。

規劃檔案架構

以「會員中心」為實例,我們將頁面拆分為一個父元件與兩個子元件:

src/
 ├─ router/
 │   └─ index.js            # 路由核心配置
 ├─ views/
 │   ├─ member/             # 存放子頁面
 │   │   ├─ Profile.vue     # 子頁面:個人資料
 │   │   └─ Orders.vue   # 子頁面:訂單列表
 │   ├─ Member.vue          # 父頁面:外殼
 │   └─ ...
 ├─ App.vue
 └─ main.js

父元件配置:準備 <router-view />

父元件 Member.vue 扮演的是 Layout(版面配置)的角色,它決定了子頁面要顯示在哪裡。

Member.vue

vue
<template>
  <h1>會員中心</h1>
  <router-link to="/member/profile">個人資料</router-link>|
  <router-link to="/member/orders">訂單列表</router-link>
  <RouterView />
</template>

子元件配置

這兩個元件會被渲染在父頁面的 <router-view /> 位置。

Profile.vue

vue
<template>
  <h3>會員個人資料</h3>
</template>

Orders.vue

vue
<template>
  <h3>訂單歷史紀錄</h3>
</template>

路由表設定:使用 children 屬性

在路由設定檔中,我們利用 children 陣列來定義層級關係。注意:子路由的 path 通常不需要加斜線 /。如果加了 / 會被視為從根目錄開始。

js
import { createRouter, createWebHistory } from "vue-router";

export default createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/",
      name: "name",
      component: () => import("@/views/Home.vue"),
    },
    {
      path: "/about",
      name: "about",
      component: () => import("@/views/About.vue"),
    },
    {
      path: "/product/:id",
      name: "product",
      component: () => import("@/views/Product.vue"),
    },
    {
      path: "/member",
      component: () => import("@/views/Member.vue"),
      children: [
        {
          // 當路徑為 /member 時,自動重新導向至 profile
          path: "",
          name: "member",
          redirect: "/member/profile",
        },
        {
          // 注意:子路由 path 通常不加「/」,會自動串接在父層之後
          path: "profile",
          name: "member-profile",
          component: () => import("@/views/member/Profile.vue"),
        },
        {
          // 注意:子路由 path 通常不加「/」,會自動串接在父層之後
          path: "orders",
          name: "member-orders",
          component: () => import("@/views/member/Orders.vue"),
        },
      ],
    },
    {
      path: "/:pathMatch(.*)*",
      redirect: "/",
    },
  ],
});

關鍵規則與開發細節

子路由 Path 的斜線問題

  • path: "profile" (不加斜線):網址會自動拼接為 /member/profile
  • path: "/profile" (加斜線):會被視為 根路徑,網址會變成 /profile 而非 /member/profile,雖然它依然是 Member.vue 的子路由。建議子層路徑統一 不加斜線 以保持結構語意。

具名路由的建議

通常在開發巢狀路由時,建議把 name: 'member' 從父層拿掉或移到子層,因為訪問 /member 時,它會立刻跳轉到 /member/profile,這時父層的 name 其實很少被直接用到。亦可移除因為導向父路由名稱時,系統不確定要停在父層還是直接進入預設子層的警告。

總結

巢狀路由是 Vue 開發中處理 Layout 版面配置的核心。透過 children 配置與 的嵌套,您能輕鬆構建出層級分明、易於維護的 SPA 應用程式。