Vue Routerとは、URLに応じて表示するコンポーネントを切り替える、Vue公式のルーティングライブラリです。 ページを再読み込みせずに画面を切り替えるSPA(シングルページアプリケーション)を作るときに使います。2026年9月時点の最新版は Vue Router 5.3.1 で、Vue 3 と組み合わせて使います。

この記事では、routes 配列で書く従来の方法と、v5で本体に統合されたファイルベースルーティング(src/pages のファイルからルートを自動生成し、ルート名に型が付く方式)の両方をコピペで動くコードで解説します。さらに、Chromium で実際にリンクをクリックしたときのURLと画面の結果、ガードでの転送、404、存在しないルート名のエラー文、遅延読み込みで分かれたビルド出力をそのまま載せています。構成は Vite を使う現在の標準の形です。

Vue Routerの早見表

やりたいこと 書き方(Vue Router 5)
ルーターを作る createRouter({ history: createWebHistory(), routes })
アプリに登録する createApp(App).use(router)
リンクを置く <RouterLink to="/about">概要</RouterLink>
表示場所を決める <RouterView />
URLの一部を受け取る(動的ルート) path: '/items/:id' → route.params.id
数字だけ受け付ける path: '/items/:id(\\d+)'
?q=... を読む・書く route.query.q / router.replace({ query: { q } })
名前で遷移する { name: 'item', params: { id: 42 } }
JSから遷移する router.push(...) / router.replace(...) / router.back()
親子の画面(ネスト) children: [...] + 親に <RouterView />
params を props で受け取る ルートに props: true
全ページ共通のチェック router.beforeEach((to) => {...})
特定ルートだけチェック ルートに beforeEnter
画面を離れる前に確認 onBeforeRouteLeave(() => false)
ページごとに分割して読み込む component: () => import('./views/X.vue')
404ページ path: '/:pathMatch(.*)*' を最後に置く
遷移時のスクロール位置 scrollBehavior(to, from, saved) {...}
ファイルからルートを自動生成(v5) vite.config に VueRouter()(vue-router/vite)

ガードは「値を返す」書き方が標準です。return false で中止、return { name: 'login' } で転送、何も返さなければ進みます。第3引数の next() は v5 の型定義で非推奨です。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Vue Routerの使い方|v5対応・ガードと404を実行結果つきで」

検証環境

項目 バージョン
Node.js 22.22.2
vue 3.5.43
vue-router 5.3.1
vite / @vitejs/plugin-vue 8.3.1 / 6.0.9
型チェック typescript 6.0.3 + vue-tsc 3.3.11
画面確認 Playwright 1.56.1 + Chromium

新規なら npm create vue@latest で「Router」を選ぶと同じ構成が作られます。既存のプロジェクトには次のコマンドで追加します。

npm i vue-router@5

v4からv5で変わったこと

Vue Router 5(5.0.0 は2026年1月29日公開)は、別パッケージだった unplugin-vue-router を本体に統合した移行用のリリースです。公式の移行ガイドでは、「unplugin-vue-router を使っていない v4 ユーザーには破壊的変更がない」とされています。

項目 v4 v5
routes 配列で書く従来の方法 ○ そのまま動く
ファイルベースルーティング 別パッケージ unplugin-vue-router 本体の vue-router/vite
自動生成ルートの読み込み vue-router/auto-routes(unplugin経由) vue-router/auto-routes
型付きルート(ルート名の補完) unplugin が必要 本体だけで生成(route-map.d.ts)
データローダー unplugin-vue-router/data-loaders/basic vue-router/experimental(実験的)
ガードの next() 使える(ドキュメントは値を返す書き方を推奨) 型定義で @deprecated、値を返す書き方へ
peerDependencies の vue ^3.5.0 ^3.5.34 || ^4.0.0
IIFEビルド devtools-api を同梱 @vue/devtools-api を含まない
次のメジャー(v6) ― ESMのみ・非推奨APIを削除予定

unplugin-vue-router から移る場合は、import 先を次のように書き換えます(公式移行ガイドより)。

旧 新
unplugin-vue-router/vite vue-router/vite
unplugin-vue-router vue-router/unplugin
unplugin-vue-router/data-loaders/basic vue-router/experimental
/// <reference types="unplugin-vue-router/client" /> 削除(生成される route-map.d.ts を tsconfig に含める)

routes配列でルーティングを書く(従来の方法)

まずは、多くのプロジェクトで使われている routes 配列で書く方法です。この1ファイルに、動的ルート・ネスト・ガード・遅延読み込み・404・スクロールをまとめました。

ルーターの定義(コピペ用)

// src/router.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from './views/HomeView.vue'
import { isLoggedIn } from './auth'

const routes = [
  { path: '/', name: 'home', component: HomeView },
  // 遅延読み込み:このページを開いたときに別ファイル(チャンク)を読み込む
  { path: '/about', name: 'about', component: () => import('./views/AboutView.vue') },
  { path: '/items', name: 'items', component: () => import('./views/ItemList.vue') },
  // 動的ルート::id の部分が params.id になる(\\d+ で数字だけ)
  { path: '/items/:id(\\d+)', name: 'item', component: () => import('./views/ItemDetail.vue'), props: true },
  // ネストしたルート:UserLayout の中の <RouterView> に子が表示される
  {
    path: '/users/:userId',
    component: () => import('./views/UserLayout.vue'),
    children: [
      { path: '', name: 'user', component: () => import('./views/UserProfile.vue') },
      { path: 'tasks', name: 'user-tasks', component: () => import('./views/UserTasks.vue') },
    ],
  },
  {
    path: '/admin',
    name: 'admin',
    component: () => import('./views/AdminView.vue'),
    meta: { requiresAuth: true },
  },
  {
    path: '/edit',
    name: 'edit',
    component: () => import('./views/EditView.vue'),
    // ルート単位のガード:クエリに from がないと入れない例
    beforeEnter: (to) => {
      if (!to.query.from) return { name: 'home' }
    },
  },
  { path: '/login', name: 'login', component: () => import('./views/LoginView.vue') },
  // 404:どのルートにも一致しないパスをすべて受ける
  { path: '/:pathMatch(.*)*', name: 'not-found', component: () => import('./views/NotFound.vue') },
]

const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) return savedPosition // 戻る・進むでは元の位置へ
    if (to.hash) return { el: to.hash, behavior: 'smooth' } // #見出し へ
    return { top: 0 } // それ以外はページの先頭へ
  },
})

// 全体のガード:meta.requiresAuth のページは未ログインならログイン画面へ
router.beforeEach((to) => {
  if (to.meta.requiresAuth && !isLoggedIn.value) {
    return { name: 'login', query: { redirect: to.fullPath } }
  }
})

export default router
// src/auth.js(学習用の簡易版。実務では Pinia のストアに置く)
import { ref } from 'vue'
export const isLoggedIn = ref(false)
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

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

RouterLink と RouterView(App.vue)

<!-- src/App.vue -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

<template>
  <nav>
    <RouterLink to="/">ホーム</RouterLink> |
    <RouterLink :to="{ name: 'about' }">概要</RouterLink> |
    <RouterLink :to="{ name: 'items', query: { q: 'ペン' } }">備品検索</RouterLink> |
    <RouterLink :to="{ name: 'item', params: { id: 42 } }">備品42</RouterLink> |
    <RouterLink :to="{ name: 'user-tasks', params: { userId: 7 } }">ユーザー7のタスク</RouterLink> |
    <RouterLink :to="{ name: 'admin' }">管理</RouterLink>
  </nav>
  <p id="path">現在のパス: {{ route.fullPath }}</p>
  <RouterView />
</template>

<style>
/* 現在のページのリンクには router-link-active クラスが付く */
.router-link-active { font-weight: bold; }
</style>

<RouterLink> は <a> タグとして描画され、クリックしてもページ全体を読み込み直しません。 to は 「名前 + params」で書くと、URLの形を変えてもリンク側を直さずに済みます。

動的ルート・クエリ・プログラム遷移

動的ルートを props で受け取る

<!-- src/views/ItemDetail.vue -->
<script setup>
import { useRouter } from 'vue-router'
// ルートに props: true を付けたので params.id が props で届く(文字列)
const props = defineProps({ id: String })
const router = useRouter()
</script>

<template>
  <h1 id="title">備品 {{ props.id }} の詳細</h1>
  <button id="next" @click="router.push({ name: 'item', params: { id: Number(props.id) + 1 } })">次の備品</button>
  <button id="back" @click="router.back()">戻る</button>
</template>

props: true にすると、コンポーネントが useRoute() に依存しなくなり、単体テストや再利用がしやすくなります。 params は常に文字列で届く点に注意してください。

同じルートの中で params だけが変わる(/items/42 → /items/43)とき、コンポーネントは作り直されず再利用されます。 onMounted でデータを取っている場合は2回目が走らないため、watch(() => props.id, ...) で変化に反応させます。

クエリを読み書きする

<!-- src/views/ItemList.vue -->
<script setup>
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'

const route = useRoute()
const router = useRouter()
const items = ['ボールペン', '蛍光ペン', 'ノート', 'ホチキス']
const q = computed(() => route.query.q ?? '')
const hits = computed(() => items.filter((i) => i.includes(q.value)))

function search(e) {
  // 履歴を増やさずにクエリだけ書き換える
  router.replace({ query: { q: e.target.value } })
}
</script>

<template>
  <h1 id="title">備品一覧</h1>
  <input :value="q" @input="search" placeholder="絞り込み" />
  <ul id="hits"><li v-for="i in hits" :key="i">{{ i }}</li></ul>
</template>

検索条件をクエリに入れると、URLの共有で同じ絞り込みを再現できます。

push・replace・back の使い分け

メソッド 動き 使う場面
router.push(to) 履歴に追加して移動 ボタンで次の画面へ
router.replace(to) 今の履歴を置き換えて移動 検索条件の反映、ログイン後の転送
router.back() / router.go(-1) 1つ戻る 「戻る」ボタン

ネストしたルート

<!-- src/views/UserLayout.vue -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

<template>
  <h1 id="title">ユーザー {{ route.params.userId }}</h1>
  <RouterLink :to="{ name: 'user' }">プロフィール</RouterLink> |
  <RouterLink :to="{ name: 'user-tasks' }">タスク</RouterLink>
  <section id="child"><RouterView /></section>
</template>

親コンポーネントの中にもう1つ <RouterView /> を置くと、そこに children のコンポーネントが表示されます。 子ルートの path: '' は、親のURL(/users/7)そのものを開いたときに表示されます。名前付きの子ルートへのリンクでは、親の params(userId)は今の値が引き継がれるので省略できます。

ナビゲーションガードでログインチェック

ガードには3つの置き場所があります。

種類 書く場所 主な用途
router.beforeEach ルーター全体 ログインチェック、権限、ページタイトル
beforeEnter ルート定義 そのルートだけの入場条件
onBeforeRouteLeave / onBeforeRouteUpdate コンポーネント 未保存の確認、params変化への対応
router.afterEach ルーター全体 アクセス解析の送信など(遷移は変えられない)

ガードの戻り値で遷移が決まります。

戻り値 結果
undefined / true(何も返さない) そのまま進む
false 遷移を取り消す(今のURLに留まる)
ルートの位置({ name: 'login' } や '/login') そこへ転送する
例外を投げる 遷移を中止し、router.onError に渡る

ログイン後に元のページへ戻す

<!-- src/views/LoginView.vue -->
<script setup>
import { useRoute, useRouter } from 'vue-router'
import { isLoggedIn } from '../auth'

const route = useRoute()
const router = useRouter()

function login() {
  isLoggedIn.value = true
  // beforeEach で付けた redirect に戻す
  router.push(route.query.redirect ?? '/')
}
</script>

<template>
  <h1 id="title">ログイン</h1>
  <button id="login" @click="login">ログインする</button>
</template>

redirect の値は、/ で始まるアプリ内のパスだけを受け付けるようにすると安全です(例:typeof r === 'string' && r.startsWith('/') && !r.startsWith('//'))。外部サイトへ転送されるのを防げます。

未保存の入力があれば離脱を確認する

<!-- src/views/EditView.vue -->
<script setup>
import { ref } from 'vue'
import { onBeforeRouteLeave } from 'vue-router'

const text = ref('')
onBeforeRouteLeave(() => {
  if (text.value && !window.confirm('保存していない入力があります。移動しますか?')) {
    return false // 遷移を取り消す
  }
})
</script>

<template>
  <h1 id="title">タスク編集</h1>
  <input id="memo" v-model="text" />
</template>

タブを閉じる・再読み込みは対象外なので、ブラウザの beforeunload イベントで別に対応します。

404ページ(catch-all)

<!-- src/views/NotFound.vue -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

<template>
  <h1 id="title">ページが見つかりません</h1>
  <p id="nf">pathMatch: {{ JSON.stringify(route.params.pathMatch) }}</p>
</template>

/:pathMatch(.*)* の末尾の * は「0個以上の区切り」を表し、route.params.pathMatch がパスを / で分けた配列になります。 下の実行結果のとおり、/items/abc のように数字制約(\\d+)に合わないURLも 404 に届きます。

実行結果:Chromiumで遷移させた結果

上のアプリを vite preview --port 7410 で起動し、Playwright で操作して「パス / 見出し」を読み取りました。

初期表示 => 現在のパス: / / ホーム
RouterLink(params) => 現在のパス: /items/42 / 備品 42 の詳細
router.push => 現在のパス: /items/43 / 備品 43 の詳細
router.back => 現在のパス: /items/42 / 備品 42 の詳細
RouterLink(query) => 現在のパス: /items?q=%E3%83%9A%E3%83%B3 / 備品一覧
  hits: ボールペン,蛍光ペン
入力でquery更新 => 現在のパス: /items?q=%E3%83%8E / 備品一覧
  hits: ノート
ネスト => 現在のパス: /users/7/tasks / ユーザー 7
  child: タスク一覧画面
未ログインで管理へ => 現在のパス: /login?redirect=/admin / ログイン
ログイン後 => 現在のパス: /admin / 管理画面
/edit(fromなし) => 現在のパス: / / ホーム
/edit?from=menu => 現在のパス: /edit?from=menu / タスク編集
confirm表示: 保存していない入力があります。移動しますか?
入力ありで離脱→キャンセル => 現在のパス: /edit?from=menu / タスク編集
/items/abc => 現在のパス: /items/abc / ページが見つかりません
   pathMatch: ["items","abc"]
/no/such/page => 現在のパス: /no/such/page / ページが見つかりません
   pathMatch: ["no","such","page"]

ポイント:

  • 日本語のクエリはURLではエンコードされるが、route.query.q では元の文字列で読める
  • beforeEach で未ログインの /admin が /login?redirect=/admin に転送され、ログイン後に /admin に戻った
  • beforeEnter は条件に合わないと転送(/edit → /)、合えば入場できた
  • onBeforeRouteLeave で false を返すとURLも画面も元のままだった

存在しないルート名・params不足のエラー文

開発サーバー(vite --port 7412)で、間違った router.push を実行したときのエラーです。

router.push({ name: 'nope' })
→ Error: No match for
 {"name":"nope","params":{}}

router.push({ name: 'item' })   // params.id を渡していない
→ Error: Missing required param "id"

どちらも Promise の reject ではなく、push を呼んだ時点で例外として投げられました。 本番ビルドではエラー文が短縮されるため、開発中に気づけるよう後述の型付きルートを使うと安心です。

遅延読み込みでチャンクが分かれることを確認

component: () => import(...) と書いたページは、ビルド時に別ファイルに分かれます。実際の vite build の出力です。

✓ 36 modules transformed.
dist/assets/UserTasks-DC4PktO_.js     0.17 kB │ gzip:  0.18 kB
dist/assets/AboutView-DnB-sd-Y.js     0.19 kB │ gzip:  0.19 kB
dist/assets/NotFound-kb5wVF03.js      0.32 kB │ gzip:  0.29 kB
dist/assets/ItemDetail-DpvaA54w.js    0.43 kB │ gzip:  0.34 kB
dist/assets/ItemList-d2i59CSM.js      0.60 kB │ gzip:  0.46 kB
dist/assets/index-BuVltqlJ.js        90.68 kB │ gzip: 35.27 kB
(ほかに UserProfile・AdminView・LoginView・EditView・UserLayout のチャンク。抜粋)

ブラウザで読み込まれたJSも確認しました。

初期表示で読み込んだJS: index-BuVltqlJ.js
「概要」クリックで追加読み込み: AboutView-DnB-sd-Y.js

最初は本体(index-*.js)だけを読み込み、「概要」を開いた時点で AboutView-*.js が追加で読み込まれました。 最初に表示する HomeView は通常の import のまま本体に含め、それ以外を遅延読み込みにするのが基本の形です。

履歴モードとサーバー設定

履歴モード URLの形 サーバー設定 向いている場面
createWebHistory() /items/42 すべてのパスで index.html を返す設定が必要 通常のWebサイト(推奨)
createWebHashHistory() /#/items/42 不要 設定を変えられない静的ホスティング
createMemoryHistory() URLは変わらない 不要 SSR、テスト

createWebHistory() では、/items/42 を直接開いたときにサーバーがそのパスのファイルを探します。 ビルド結果(dist)を、フォールバック設定のない静的サーバー(python3 -m http.server 7411)と vite preview(フォールバックあり)で配信して比べました。

http://localhost:7411/          → HTTP 200
http://localhost:7411/items/42  → HTTP 404   ← 静的サーバーはファイルがないので404
http://localhost:7410/items/42  → HTTP 200   ← vite preview は index.html を返す

アプリ内のリンクで移動する分には問題なく、再読み込みやURL直打ちのときだけ404になるのが特徴です。本番のWebサーバーでは、存在しないパスを index.html に向ける設定をします。

location / {
  try_files $uri $uri/ /index.html;
}

この設定では存在しないURLも200で返るため、404は Vue 側のページで表示します。

ファイルベースルーティングと型付きルート(v5の新しい書き方)

v5 では、src/pages にファイルを置くだけでルートが作られ、ルート名や params に型が付きます。 設定は Vite プラグインを1つ足すだけです。

設定とフォルダ構成

npm i vue-router@5
npm i -D typescript vue-tsc   # 型チェックする場合
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import VueRouter from 'vue-router/vite'

export default defineConfig({
  plugins: [
    // ファイルベースルーティング(vue() より前に置く)
    VueRouter({ dts: 'src/route-map.d.ts' }),
    vue(),
  ],
})
// src/main.ts
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { routes, handleHotUpdate } from 'vue-router/auto-routes'
import App from './App.vue'

const router = createRouter({ history: createWebHistory(), routes })
if (import.meta.hot) handleHotUpdate(router)

createApp(App).use(router).mount('#app')
ファイル 生成されるパス ルート名
src/pages/index.vue / /
src/pages/items/[id].vue /items/:id /items/[id]
src/pages/users/[userId].vue(親) /users/:userId /users/[userId]
src/pages/users/[userId]/tasks.vue(子) /users/:userId/tasks /users/[userId]/tasks
src/pages/[...path].vue /:path(.*)(404) /[...path]

users/[userId].vue と同名のフォルダ users/[userId]/ を置くと、フォルダ内のファイルが子ルートになり、親の <RouterView /> に表示されます。 既定の読み込みは importMode: 'async' なので、ページごとの遅延読み込みも自動です(ビルドで _id_-*.js・about-*.js などに分かれました)。

<!-- src/pages/items/[id].vue -->
<script setup lang="ts">
import { useRoute } from 'vue-router'
// ルート名を渡すと route.params.id が string として補完される
const route = useRoute('/items/[id]')
</script>

<template><h1 id="title">備品 {{ route.params.id }} の詳細</h1></template>
<!-- src/pages/[...path].vue -->
<script setup lang="ts">
// definePage でルートの meta や name を追加できる(import 不要のマクロ)
definePage({ meta: { title: '404' } })
</script>

<template><h1 id="title">ページが見つかりません</h1></template>

Chromium での確認結果です(vite preview --port 7413)。

初期表示 => 現在のパス: / / ホーム
pages/items/[id].vue => 現在のパス: /items/42 / 備品 42 の詳細
pages/users/[userId]/tasks.vue => 現在のパス: /users/7/tasks / ユーザー 7
  child: タスク一覧画面
pages/about.vue => 現在のパス: /about / このアプリについて
pages/[...path].vue => 現在のパス: /nothing/here / ページが見つかりません

型付きルートでタイプミスを見つける

ビルド時に src/route-map.d.ts が生成され、すべてのルート名と params の型(例:'/items/[id]' の params は { id: string })が書き込まれます。

わざと間違えたコードを vue-tsc --noEmit で型チェックしました。

// src/typo.ts
import { useRouter } from 'vue-router'

export function goItem() {
  const router = useRouter()
  router.push({ name: '/item/[id]', params: { id: '1' } })   // ルート名のタイプミス
  router.push({ name: '/items/[id]' })                         // params の書き忘れ
  router.push({ name: '/items/[id]', params: { itemId: '1' } }) // param 名の間違い
}
src/typo.ts(5,15): error TS2345: ...
    Type '"/item/[id]"' is not assignable to type '"/" | "/[...path]" | "/about" | "/items/" | "/items/[id]" | "/users/[userId]" | "/users/[userId]/tasks" | undefined'. Did you mean '"/items/[id]"'?
src/typo.ts(7,48): error TS2345: ...
    Object literal may only specify known properties, and 'itemId' does not exist in type '{ id: string | number; }'.

ルート名のタイプミスは「Did you mean '/items/[id]'?」と候補つきで、param名の間違いも型エラーになりました。 一方、params をまるごと書き忘れた6行目は型エラーになりませんでした。 名前付きルートで params を省略すると今のURLの params を引き継ぐ仕様があるため、型の上では省略できる扱いになっています。今のURLに id がない画面から呼ぶと、前の節のとおり実行時に Missing required param "id" になるので、params を持つルートへの遷移は params まで書く習慣をつけると確実です。

※ vue-tsc 3.3.11 は typescript 7.0.2 では ERR_PACKAGE_PATH_NOT_EXPORTED で起動しなかったため、6.0.3 で実行しました。

どちらの書き方を選ぶか

観点 routes 配列 ファイルベース(v5)
設定の見通し 1ファイルで全体が見える フォルダ構成がそのままURL
ルート名・params の型 自分で型を書く 自動生成
既存プロジェクト そのまま 移行にはファイル配置の変更が必要

新規かつTypeScriptならファイルベース、既存プロジェクトは routes 配列のまま v5 に上げるのが負担の少ない選び方です。どちらも同じ createRouter の上で動くので、ガードや RouterLink の書き方は共通です。

よくあるつまずきと直し方

症状 原因 直し方
No match for {"name":...} ルート名の間違い 名前を確認。型付きルートで事前に検出
Missing required param "id" params の書き忘れ params: { id } を渡す
再読み込みで404 サーバーにフォールバック設定がない try_files ... /index.html など
params が変わっても画面が更新されない コンポーネントが再利用される watch(() => route.params.id, ...) か onBeforeRouteUpdate
ガードが無限にリダイレクトする 転送先にも同じ条件がかかる 転送先(login)を条件から外す

よくある質問

Q. Vue Router 4 のプロジェクトは v5 に上げるべきですか? A. routes 配列で書いているなら、公式の移行ガイドで破壊的変更はないとされています。v6 では非推奨APIの削除とESMのみへの移行が予定されているため、v5 で next() を値を返す書き方に直すなど、少しずつ準備しておくと移行が楽になります。

Q. useRoute と useRouter の違いは何ですか? A. useRoute() は「今のルートの情報」(params・query・fullPath・meta)を読むためのもの、useRouter() は「ルーター本体」で、push などの遷移やガードの登録に使います。

Q. ログイン状態はどこに持てばよいですか? A. 小さな例では ref をモジュールに置く形で十分ですが、アプリ全体で使う状態は Pinia のストアにまとめると、ガードからもコンポーネントからも同じ値を扱えて管理しやすくなります。ガードの中で useXxxStore() を呼べば使えます。

まとめ

  • Vue Router 5.3.1 が最新。routes 配列の書き方は v4 からそのまま動く
  • v5 の目玉は本体に統合されたファイルベースルーティング。vue-router/vite を足すだけで ルート名と params に型が付く
  • リンクは RouterLink を名前 + params で、表示は RouterView、JSからは push / replace
  • ガードは値を返して制御(false で中止、位置を返して転送)。next() は v5 で非推奨
  • () => import() でページごとにチャンクが分かれ、開いたときに読み込まれることをビルドとブラウザで確認
  • 404 は /:pathMatch(.*)*、履歴モードはサーバーで index.html へのフォールバックを設定

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Vue Routerの使い方|v5対応・ガードと404を実行結果つきで」

株式会社RJCでは、ルーティングの設計や型で間違いを早く見つける工夫を、プロジェクトの中で仲間と試しながら共有しています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?