採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

Vue Router — ネストルート

テクノロジ系 / L04 routing — ルーティング

Vue Router — ネストルート

children で階層化

const routes = [
  {
    path: "/users",
    component: UserLayout,
    children: [
      { path: "", component: UserList },              // /users
      { path: ":id", component: UserDetail },         // /users/:id
      { path: ":id/edit", component: UserEdit },      // /users/:id/edit
    ],
  },
];

children で子ルート。

子の path は親を含めない (相対指定)。

RouterView をネスト

<!-- UserLayout.vue -->
<template>
  <div class="user-section">
    <aside>
      <UserSidebar />
    </aside>
    <main>
      <RouterView />     <!-- 子ルートが描画される -->
    </main>
  </div>
</template>

/users でも /users/123 でも UserLayout 内に描画。

共有レイアウトのメリット

  • ヘッダ・サイドバーを毎ページ書かない
  • 子ルート切替時に 親のDOMは再利用 (高速)
  • 共通ロジック (認証 / 通知) を親に置ける

ネストの再描画コスト

/users → /users/1 → /users/2
   ↑ UserLayout は1度だけ作られる、UserList ↔ UserDetail だけ切り替わる

→ 親側で重いデータ取得をしても、子切替で再取得されない。

ナビゲーション体験が滑らか。

ネストの典型例

[
  {
    path: "/",
    component: MainLayout,
    children: [
      { path: "", component: HomePage },
      { path: "about", component: AboutPage },
      {
        path: "dashboard",
        component: DashboardLayout,
        children: [
          { path: "", component: DashboardHome },
          { path: "settings", component: Settings },
          { path: "users", component: Users },
        ],
      },
    ],
  },
  { path: "/login", component: LoginPage },   // レイアウト外
]

ログイン画面など特殊なものは親レイアウトから外す。

まとめ

  • children で子ルート (path は相対)
  • 親コンポーネントに <RouterView> を置く
  • レイアウトとコンテンツの分離が自然
  • 共通DOMは再描画されず性能良し
  • レイアウト外の特殊ページは親から外す

最後は ナビゲーションガード

考えてみよう

既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。

Lv1: 基本 — children

問題

const routes = [
  {
    path: "/users",
    component: () => import("./pages/UsersLayout.vue"),
    children: [
      { path: "", component: () => import("./pages/UserList.vue") },
      { path: ":id", component: () => import("./pages/UserDetail.vue") },
      { path: ":id/edit", component: () => import("./pages/UserEdit.vue") },
    ],
  },
];
<!-- UsersLayout.vue -->
<script setup>
import { RouterView } from "vue-router";
</script>

<template>
  <div class="users-section">
    <aside><nav>Sidebar</nav></aside>
    <main><RouterView /></main>
  </div>
</template>

合格基準

  • /users で UserList
  • /users/1 で UserDetail
  • どちらも UsersLayout 内に描画

Lv2: 応用 — レイアウトの DOM 保持

問題

<!-- UsersLayout.vue -->
<script setup>
import { onMounted, onUnmounted } from "vue";

onMounted(() => console.log("Layout mounted"));
onUnmounted(() => console.log("Layout unmounted"));
</script>

/users → /users/1 → /users/2 と遷移して、Layout が 1回しか mount されない ことを観察。

合格基準

  • ネスト内遷移で親再描画なし
  • 高速

Lv3: 発展 — 多階層ネスト

問題

const routes = [
  {
    path: "/",
    component: MainLayout,
    children: [
      { path: "", component: Home },
      {
        path: "dashboard",
        component: DashboardLayout,
        children: [
          { path: "", component: DashboardHome },
          { path: "settings", component: Settings },
          {
            path: "users",
            component: UserSection,
            children: [
              { path: "", component: UserList },
              { path: ":id", component: UserDetail },
            ],
          },
        ],
      },
    ],
  },
  { path: "/login", component: LoginPage },   // 親レイアウト外
];

/dashboard/users/1 で 3階層のレイアウトが入れ子表示される。

合格基準

  • 3階層 nest 動作
  • /login だけレイアウト外

提出

submission.md に3問の回答を。