Vue Routerはシングルページアプリケーション(SPA)におけるコンポーネント間のナビゲーションを管理するためのVue.js公式ルーティングライブラリです。本記事ではVue Routerの基本的な使い方と主要機能について解説します。
Vue Routerとは
Vue Routerは、従来のマルチページアプリケーションで使用されるサーバーサイドルーティングとは異なり、クライアントサイドでのルーティングを提供します。これによりページ全体のリロードなしでコンテンツを切り替えることが可能になります。
基本的なセットアップ
VueプロジェクトでVue Routerを使用する基本的なセットアップ方法を見てみましょう。
HTML構造
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue Router Example</title>
</head>
<body>
<div id="app">
<h1>ルーティングデモ</h1>
<nav>
<!-- router-linkコンポーネントでナビゲーションリンクを作成 -->
<router-link to="/home">ホーム</router-link>
<router-link to="/about">关于我们</router-link>
<router-link to="/contact">お問い合わせ</router-link>
</nav>
<!-- ルートにマッチしたコンポーネントがここに描画されます -->
<router-view></router-view>
</div>
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>
</body>
</html>
JavaScript実装
// ルーティングに必要なVueとVueRouterをインポート
const { Vue, VueRouter } = window;
// 1. ルーティング対象のコンポーネントを定義
const HomeView = {
template: '<div><h2>ホームページ</h2><p>ようこそ、私たちのサイトへ!</p></div>'
};
const AboutView = {
template: '<div><h2>关于我们</h2><p>私たちについての詳細情報です。</p></div>'
};
const ContactView = {
template: '<div><h2>お問い合わせ</h2><p>ご連絡はこちらからお願いします。</p></div>'
};
// 2. ルート定義
const routes = [
{ path: '/home', component: HomeView },
{ path: '/about', component: AboutView },
{ path: '/contact', component: ContactView }
];
// 3. VueRouterインスタンスを作成
const router = new VueRouter({
routes
});
// 4. ルートを含むVueインスタンスをマウント
const app = new Vue({
router
}).$mount('#app');
動的ルートパラメータ
動的ルートパラメータを使用すると、URLの一部を変数として扱うことができます。
const UserView = {
template: '<div><h2>ユーザー情報</h2><p>ID: {{ userId }}</p></div>',
computed: {
userId() {
return this.$route.params.id;
}
}
};
const dynamicRoutes = [
{
path: '/user/:id',
component: UserView,
props: true // propsでルートパラメータをコンポーネントに渡す
}
];
const dynamicRouter = new VueRouter({
routes: dynamicRoutes
});
ルートパラメータの変更への対応
ルートパラメータが変更された場合、コンポーネントインスタンスは再利用されます。この変化に対応するには、watchプロパティを使用します。
const ProfileView = {
template: '<div><h2>プロフィール</h2><p>ユーザーID: {{ userId }}</p></div>',
watch: {
'$route'(to, from) {
// ルート変更時の処理
console.log('ルートが変更されました:', to.params.id);
this.fetchUserData(to.params.id);
}
},
methods: {
fetchUserData(userId) {
// ユーザーデータを取得する処理
console.log(`ユーザーID ${userId} のデータを取得中...`);
}
}
};
高度なマッチングパターン
Vue Routerはpath-to-regexpを使用しているため、様々な高度なマッチングパターンをサポートしています。
const advancedRoutes = [
// オプションのパラメータ
{ path: '/products/:category?', component: CategoryView },
// 複数のパラメータ
{ path: '/blog/:year/:month/:day', component: BlogView },
// 正規表現によるマッチング
{ path: '/search/:query(\\d+)', component: SearchView }
];
ルートの優先順位
複数のルートが同じパスにマッチする場合、定義された順序が優先されます。
const priorityRoutes = [
// このルートが優先される
{ path: '/user/:id', component: UserProfile },
// このルートは優先されない
{ path: '/user/admin', component: AdminView }
];
プログラムによるナビゲーション
router-link以外にも、JavaScriptコードから直接ナビゲーションを行うことができます。
// router.push() - historyスタックに新しいエントリを追加
router.push('/home');
router.push({ name: 'user', params: { id: 123 } });
// router.replace() - 現在のhistoryエントリを置き換え
router.replace('/about');
// router.go() - historyスタック内を移動
router.go(1); // 前進
router.go(-1); // 戻る
名前付きルート
ルートに名前を付けることで、ナビゲーションをより直感的に行えます。
const namedRoutes = [
{
path: '/product/:id',
name: 'productDetail',
component: ProductDetail
}
];
// 名前付きルートを使用したナビゲーション
router.push({ name: 'productDetail', params: { id: 456 } });
名前付きビュー
複数のビューを同時に表示する場合、名前付きビューを使用します。
<router-view name="header"></router-view>
<router-view name="main"></router-view>
<router-view name="footer"></router-view>
const namedViews = [
{
path: '/',
components: {
default: MainContent,
header: HeaderView,
footer: FooterView
}
}
];
リダイレクトとエイリアス
リダイレクト
特定のパスへのアクセスを別のパスにリダイレクトできます。
const redirectRoutes = [
{ path: '/old-path', redirect: '/new-path' },
{ path: '/user', redirect: { name: 'userProfile' } }
];
エイリアス
URLを保持したまま、異なるパスにマッチさせる機能です。
const aliasRoutes = [
{
path: '/dashboard',
component: Dashboard,
alias: '/home'
}
];
HTML5 Historyモード
hashモードではなく、よりクリーンなURLを使用するための設定です。
const historyRouter = new VueRouter({
mode: 'history',
routes: [...]
});
ナビゲーションガード
ルート遷移を制御するためのフック機能です。
グローバルガード
router.beforeEach((to, from, next) => {
// 認証チェックなどの前処理
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
ルート固有のガード
const guardedRoutes = [
{
path: '/admin',
component: AdminPanel,
beforeEnter: (to, from, next) => {
// このルート固有のガード
if (!isAdmin()) {
next('/access-denied');
} else {
next();
}
}
}
];
コンポーネント内ガード
const ProtectedComponent = {
template: '<div>保護されたコンテンツ</div>',
beforeRouteEnter(to, from, next) {
// コンポーネントが作成される前に呼ばれる
checkPermission().then(() => {
next();
}).catch(() => {
next(false);
});
},
beforeRouteLeave(to, from, next) {
// コンポーネントが離脱する前に呼ばれる
if (confirm('本当に離脱しますか?')) {
next();
} else {
next(false);
}
}
};
データ取得
ルート遷移時にデータを取得する方法についてです。
ナビゲーション完了後のデータ取得
const PostView = {
template: `
<div>
<div v-if="loading">読み込み中...</div>
<div v-if="error">{{ error }}</div>
<div v-if="post">
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
</div>
</div>
`,
data() {
return {
post: null,
loading: false,
error: null
};
},
created() {
this.fetchPost();
},
watch: {
'$route': 'fetchPost'
},
methods: {
async fetchPost() {
this.loading = true;
this.error = null;
try {
const response = await fetch(`/api/posts/${this.$route.params.id}`);
this.post = await response.json();
} catch (err) {
this.error = 'データの取得に失敗しました';
} finally {
this.loading = false;
}
}
}
};
ナビゲーション完了前のデータ取得
const AsyncPostView = {
template: `
<div>
<div v-if="loading">読み込み中...</div>
<div v-if="error">{{ error }}</div>
<div v-if="post">
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
</div>
</div>
`,
data() {
return {
post: null,
error: null
};
},
beforeRouteEnter(to, from, next) {
fetchPostData(to.params.id)
.then(post => {
next(vm => {
vm.post = post;
});
})
.catch(err => {
next(false);
});
},
watch: {
'$route'() {
this.post = null;
this.fetchPost();
}
},
methods: {
async fetchPost() {
try {
const response = await fetch(`/api/posts/${this.$route.params.id}`);
this.post = await response.json();
} catch (err) {
this.error = 'データの取得に失敗しました';
}
}
}
};
これらの機能を組み合わせることで、複雑なナビゲーションロジックを持つシングルページアプリケーションを構築することができます。Vue Routerの詳細なドキュメントは公式サイトを参照してください。