
Vue Router 動的ルーティング完全ガイド
2025-07-31はじめに
Vue.jsのルーティングシステムにおいて、動的ルーティングは現代的なWebアプリケーション開発に欠かせない機能です。この記事では、Vue Routerの動的ルーティングについて、基本概念から高度な活用方法まで、実践的な例を交えて詳しく解説します。
動的ルーティングとは?
動的ルーティングとは、URLの一部を変数として扱い、同じコンポーネントで異なるコンテンツを表示する仕組みです。例えば、ユーザーIDや商品IDなど、変化する値をURLに含めることで、柔軟なページ設計が可能になります。

基本的な動的ルーティングの設定
動的セグメントの定義
動的ルーティングを設定するには、ルートパスにコロン(:
)で始まるセグメントを追加します。
const routes = [
{
path: '/user/:id',
component: UserProfile
}
]
パラメータへのアクセス方法
動的セグメントの値には、以下の2つの方法でアクセスできます。
$route
オブジェクト経由:
this.$route.params.id
- propsとして受け取る(推奨):
const routes = [
{
path: '/user/:id',
component: UserProfile,
props: true
}
]
// UserProfile.vue
export default {
props: ['id']
}
複数の動的セグメント
複数の動的セグメントを組み合わせることも可能です。
{
path: '/category/:categoryId/product/:productId',
component: ProductDetail
}
動的ルーティングの高度な使い方
正規表現による制約
動的セグメントに正規表現を適用して、マッチするパターンを制限できます。
{
// 数値のIDのみマッチ
path: '/user/:id(\\d+)',
component: UserProfile
}
オプショナルな動的セグメント
セグメントの最後に?
を追加すると、オプショナルなパラメータになります。
{
// /user と /user/:id の両方にマッチ
path: '/user/:id?',
component: UserProfile
}
ワイルドカードルーティング
アスタリスク(*
)を使用すると、任意のパスにマッチさせることができます。
{
path: '/docs/*',
component: Documentation
}
動的ルーティングの実践例
ユーザープロフィールページ
const routes = [
{
path: '/user/:userId',
name: 'user-profile',
component: UserProfile,
props: true,
meta: { requiresAuth: true }
}
]
<!-- UserProfile.vue -->
<template>
<div v-if="user">
<h1>{{ user.name }}のプロフィール</h1>
<p>ユーザーID: {{ userId }}</p>
<!-- その他のユーザー情報 -->
</div>
<div v-else>
<p>ユーザーが見つかりません</p>
</div>
</template>
<script>
export default {
props: ['userId'],
data() {
return {
user: null
}
},
async created() {
try {
const response = await fetch(`/api/users/${this.userId}`)
this.user = await response.json()
} catch (error) {
console.error('ユーザー情報の取得に失敗しました:', error)
}
},
watch: {
userId() {
// 同じコンポーネント内でuserIdが変わった場合の処理
this.fetchUserData()
}
}
}
</script>
商品詳細ページ
{
path: '/products/:category/:productSlug',
component: ProductDetail,
props: route => ({
category: route.params.category,
slug: route.params.productSlug,
highlight: route.query.highlight // クエリパラメータもpropsとして渡す
})
}
動的ルーティングの注意点
コンポーネントの再利用問題
同じコンポーネントが異なるルートで使用される場合、Vueは効率化のためにコンポーネントを再利用しようとします。これにより、ライフサイクルフックが再実行されないことがあります。
解決方法:
watch
で$route
オブジェクトを監視beforeRouteUpdate
ナビゲーションガードを使用
export default {
watch: {
'$route'(to, from) {
// ルートが変更された時の処理
this.fetchData(to.params.id)
}
},
methods: {
fetchData(id) {
// データ取得処理
}
}
}
スクロール位置の保持
動的ルーティングを使用すると、ブラウザのスクロール位置が保持されることがあります。これを防ぐには、ルーターの設定でスクロール動作を制御します。
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
})
動的ルーティングのベストプラクティス
- propsモードを使用する:
$route
に直接依存するよりも、propsとして受け取る方がコンポーネントの再利用性が高まります。 - 適切な命名規則: パラメータ名は意味のあるものにしましょう(
:userId
vs:id
)。 - バリデーションを実装: 不正なパラメータ値に対処する仕組みを作りましょう。
- エラーハンドリング: 存在しないリソースへのアクセスを適切に処理しましょう。
- ローディング状態: データ取得中のローディング状態を表示しましょう。
高度なパターン
動的ルートの遅延読み込み
const routes = [
{
path: '/admin/:section',
component: () => import(`@/views/Admin${capitalizeFirstLetter(section)}.vue`),
beforeEnter: (to) => {
const section = to.params.section
if (!['dashboard', 'users', 'settings'].includes(section)) {
return '/admin/dashboard'
}
}
}
]
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}
動的ネストルート
function generateProductRoutes() {
return [
{
path: 'overview',
component: () => import('@/views/ProductOverview.vue')
},
{
path: 'specs',
component: () => import('@/views/ProductSpecs.vue')
},
{
path: 'reviews',
component: () => import('@/views/ProductReviews.vue')
}
]
}
const routes = [
{
path: '/product/:id',
component: () => import('@/views/ProductLayout.vue'),
children: generateProductRoutes()
}
]
パフォーマンス最適化
データプリフェッチ
{
path: '/article/:slug',
component: ArticleDetail,
meta: {
prefetch: true
}
}
router.beforeResolve(async (to) => {
if (to.meta.prefetch) {
await store.dispatch('fetchArticle', to.params.slug)
}
})
ルートベースのコード分割
const routes = [
{
path: '/user/:id',
component: () => import(/* webpackChunkName: "user" */ './views/UserProfile.vue')
}
]
テスト戦略
動的ルーティングのテスト例(JestとVue Test Utilsを使用):
import { mount } from '@vue/test-utils'
import { createRouter, createWebHistory } from 'vue-router'
import UserProfile from '@/views/UserProfile.vue'
describe('UserProfile.vue', () => {
const mockRoute = {
params: {
id: '123'
}
}
const mockRouter = {
push: jest.fn()
}
it('should fetch user data based on route param', async () => {
const fetchUserMock = jest.fn(() => Promise.resolve({
id: '123',
name: 'テストユーザー'
}))
const wrapper = mount(UserProfile, {
global: {
mocks: {
$route: mockRoute,
$router: mockRouter,
$api: {
fetchUser: fetchUserMock
}
}
},
props: {
id: '123'
}
})
await wrapper.vm.$nextTick()
expect(fetchUserMock).toHaveBeenCalledWith('123')
expect(wrapper.text()).toContain('テストユーザー')
})
})
よくあるエラーと解決方法
404エラーの処理
存在しない動的ルートへのアクセスを適切に処理します。
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
}
パラメータの型不一致
// 問題: 数値が必要だが文字列が渡される
this.$route.params.id // "123" (文字列)
// 解決策
const id = parseInt(this.$route.params.id, 10)
if (isNaN(id)) {
// エラーハンドリング
}
まとめ
Vue Routerの動的ルーティングは、現代的なWebアプリケーション開発において不可欠な機能です。適切に実装することで:
- 柔軟でスケーラブルなルーティングシステムを構築
- 同じコンポーネントで異なるコンテンツを表示
- URL設計を直感的でRESTfulなものに
- アプリケーションの状態をURLで表現
が可能になります。
動的ルーティングをマスターすることで、より複雑で大規模なアプリケーションも効率的に開発できるようになります。実際のプロジェクトでこれらのテクニックを試しながら、理解を深めていきましょう。