12.

Vue.js ルーティング (Vue Router) 完全ガイド

編集
この記事の要点
  • Vue Router は Vue.js 公式の SPA ルーティングライブラリ
  • Vue 3 では vue-router@4、Vue 2 では vue-router@3 を使用
  • 基本: createRouter() + createWebHistory() + routes 配列を app.use(router)
  • テンプレートでは <router-view> で表示、<router-link to="/"> で遷移
  • 動的セグメント /user/:iduseRoute().params.id で取得、Lazy Loading は () => import()

Vue Router とは

Vue Router は Vue.js 公式のクライアントサイドルーティングライブラリです。SPA (Single Page Application) において、URL と Vue コンポーネントを対応付け、ページ遷移時にコンポーネントを切り替えます。サーバーへのリクエストは発生せず、ブラウザの History API でアドレスバーを書き換えます。

Vue バージョンVue Router バージョン主な API
Vue 3vue-router@4.xcreateRouter / createWebHistory
Vue 2vue-router@3.xnew VueRouter() / mode: 'history'

インストール

# Vue 3 の場合
npm install vue-router@4

# Vue 2 の場合
npm install vue-router@3

# Vite で新規作成時はオプションで含められる
npm create vue@latest
# → "Add Vue Router for Single Page Application development?" → Yes

基本セットアップ (Vue 3 + Composition API)

// 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 },
  // Lazy Loading(コード分割)
  { path: '/contact', component: () => import('@/views/Contact.vue') },
];

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes,
});

export default router;
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

createApp(App)
  .use(router)
  .mount('#app');

テンプレートでの利用

<!-- App.vue -->
<template>
  <nav>
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link :to="{ name: 'contact' }">Contact</router-link>
  </nav>

  <!-- ここに各ルートのコンポーネントが表示される -->
  <router-view />
</template>

<router-link> は内部的に <a href> を生成しますが、クリック時に History API を使うため、ページリロードは発生しません。アクティブな状態には自動で router-link-active / router-link-exact-active クラスが付きます。

history モードの違い

モードURL 例サーバ設定
createWebHistory()/about★必須: 全 URL を index.html にフォールバック
createWebHashHistory()/#/about不要(# 以降はサーバへ送られない)
createMemoryHistory()なしSSR / テスト用

動的セグメント (URL パラメータ)

// router/index.js
const routes = [
  { path: '/user/:id', name: 'user', component: User },
  // 複数のパラメータ
  { path: '/post/:category/:slug', component: Post },
  // オプショナル + 正規表現
  { path: '/items/:id(\\d+)?', component: Items },  // 数字のみ、省略可
];
<!-- User.vue -->
<script setup>
import { useRoute, useRouter } from 'vue-router';
import { watch } from 'vue';

const route = useRoute();    // 現在のルート情報(params, query, path, name)
const router = useRouter();  // ルーター本体(push, replace, back)

console.log(route.params.id);   // /user/42 → "42"
console.log(route.query.tab);   // /user/42?tab=posts → "posts"

// パラメータ変更を監視(同じコンポーネントの使い回し時に必須)
watch(() => route.params.id, (newId, oldId) => {
  console.log(`id changed: ${oldId} → ${newId}`);
  // 再フェッチ等
});

function goHome() {
  router.push('/');                      // パス指定
  router.push({ name: 'home' });         // ルート名指定
  router.push({ name: 'user', params: { id: 99 } });
  router.replace('/about');              // 履歴に残さない
  router.back();                         // 戻る
}
</script>

<template>
  <div>User ID: {{ route.params.id }}</div>
</template>

ネストルート

const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      // /user/:id/profile
      { path: 'profile', component: UserProfile },
      // /user/:id/posts
      { path: 'posts', component: UserPosts },
      // /user/:id(デフォルト子ルート)
      { path: '', component: UserHome },
    ],
  },
];

親コンポーネント側でも <router-view /> を置くと、その位置に子ルートのコンポーネントが描画されます。

ナビゲーションガード

ルート遷移の前後にフックを差し込み、認証チェックやリダイレクトを実装できます。

// グローバルガード
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next({ name: 'login', query: { redirect: to.fullPath } });
  } else {
    next();
  }
});

// 解決後(次画面のコンポーネントロード後)
router.beforeResolve(async (to) => {
  if (to.meta.fetchOnEnter) {
    await loadData(to);
  }
});

router.afterEach((to, from) => {
  // 画面遷移後のアナリティクス送信など
  gtag('event', 'page_view', { page_path: to.fullPath });
});

// ルート別ガード
const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: { requiresAuth: true },
    beforeEnter: (to, from) => { /* ... */ },
  },
];

Lazy Loading (コード分割)

初期バンドルサイズを抑えるには、各ルートのコンポーネントを動的 import します:

const routes = [
  // ❌ 同期 import: 初期バンドルに全部入る
  { path: '/heavy', component: HeavyView },

  // ✅ 動的 import: 訪問時に別チャンクをロード
  { path: '/heavy', component: () => import('@/views/HeavyView.vue') },

  // チャンク名を指定
  {
    path: '/dashboard',
    component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue'),
  },
];

Vue 2 (vue-router 3.x) との違い

項目Vue 2 / vue-router 3Vue 3 / vue-router 4
作成new VueRouter({ routes })createRouter({ routes, history })
historymode: 'history'history: createWebHistory()
登録new Vue({ router })app.use(router)
取得 (Composition)this.$route / this.$routeruseRoute() / useRouter()
キャッチオールpath: '*'path: '/:pathMatch(.*)*'

404 ページの設定

const routes = [
  // ... 他のルート
  // 最後に: マッチしないものを全部ここへ
  { path: '/:pathMatch(.*)*', name: 'not-found', component: NotFound },
];

FAQ

Q: リロードすると 404 になる
A: createWebHistory モードはサーバ側で「全 URL を index.html にフォールバック」設定が必要です。Nginx なら try_files $uri $uri/ /index.html;、Laravel なら Route::view('/{any}', 'app')->where('any', '.*');

Q: 同じコンポーネントでパラメータだけ変わったときに再生成されない
A: Vue Router の意図的な最適化です。watch(() => route.params, ...) で監視するか、<router-view :key="$route.fullPath" /> で強制再生成します。

Q: Vue Router で SSR したい
A: Nuxt 3 を使うのが最短です。手動なら createMemoryHistory() + サーバで router.push()router.isReady() 待ち → レンダリングのフローになります。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストール(ファイルのダウンロード)
  2. npmを使用したプロジェクトの作成
  3. for 繰り返し処理
  4. ifの条件分岐とtemplateを用いたグループ化
  5. クリック時のイベント処理(on:click)
  6. modelとdata フォーム入力値とDOMへの即時反映
  7. computed(算出プロパティ)と使い方とdataとの違い
  8. ライフサイクルフック(created / mounted / updated / destroyedの使い方)
  9. $nextTickの使い方(ライフサイクルフック)
  10. メソッドの定義方法
  11. エラー一覧
  12. ルーティング設定
  13. aリンクの貼り方と動的URLの作成
  14. Mixinを利用した共通処理の記述方法
  15. v-bindによるデータ連携
  16. ヘッダー/フッターの共通コンポーネント
  17. ナビゲーションの現在ページをハイライトする方法
  18. 画面サイズの取得方法

最近更新/作成されたページ