ナビゲーションガードの実装
グローバルガード
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', name: 'top', component: TopView },
{ path: '/profile', name: 'profile', component: ProfileView }
]
})
// グローバル前置ガード
router.beforeEach((destination, origin) => {
if (destination.name === 'profile' && !isAuthenticated()) {
return { name: 'login' }
}
return true
})
// グローバル解決ガード
router.beforeResolve(async destination => {
if (destination.meta.requiresAuth) {
await verifyUserSession()
}
})
// グローバル後置フック
router.afterEach((destination, origin, navigationError) => {
logNavigation(destination.path)
})
ルート固有ガード
const routeConfig = [
{
path: '/dashboard',
component: Dashboard,
beforeEnter: (destination, origin) => {
return hasPermission(destination.query.accessLevel)
}
},
{
path: '/admin',
component: AdminPanel,
beforeEnter: [checkAdminRole, validateSession]
}
]
コンポーネント内ガード
<script>
export default {
beforeRouteEnter(destination, origin, proceed) {
proceed(vm => vm.initData())
},
beforeRouteUpdate(destination, origin) {
this.refreshContent(destination.params.id)
},
beforeRouteLeave(destination, origin) {
return this.hasUnsavedChanges ? confirm('変更を破棄しますか?') : true
}
}
</script>
ナビゲーション処理フロー
- ナビゲーション開始
- コンポーネントのbeforeRouteLeave呼出
- グローバルbeforeEach呼出
- 再利用コンポーネントのbeforeRouteUpdate呼出
- ルート設定内beforeEnter呼出
- 非同期コンポーネント解決
- アクティベート前beforeRouteEnter呼出
- グローバルbeforeResolve呼出
- ナビゲーション確定
- グローバルafterEach呼出
- DOM更新
- beforeRouteEnterのnextコールバック実行
ルートメタ情報と遅延読み込み
const routes = [
{
path: '/settings',
component: () => import('./views/SettingsPage.vue'),
meta: { requiresAuth: true, accessLevel: 2 }
}
]
router.beforeEach((destination) => {
if (destination.meta.requiresAuth) {
return validateAuth()
}
})
ナビゲーションエラーハンドリング
import { isNavigationFailure, NavigationFailureType } from 'vue-router'
async function navigateToUser() {
const result = await router.push('/user/123')
if (isNavigationFailure(result, NavigationFailureType.aborted)) {
showToast('アクセスが拒否されました')
}
}
router.afterEach((_, __, navigationError) => {
if (navigationError) {
logError(navigationError)
}
})
動的ルーティング操作
// ルート追加
router.addRoute({
path: '/reports',
component: () => import('./views/Reports.vue')
})
// ルート削除
const removeReportRoute = router.addRoute(reportRoute)
removeReportRoute()
// 別名での削除
router.removeRoute('reports')
// ネストされたルート追加
router.addRoute('admin', {
path: 'dashboard',
component: AdminDashboard
})
// ルート存在確認
if (!router.hasRoute('backup')) {
router.addRoute(backupRoute)
}