onBeforeRouteLeave
onBeforeRouteLeave composable は、コンポーネント内でルートガードを登録することを可能にします。
tips
このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。
onBeforeRouteLeave の補足解説
Nuxt でページ遷移時に特定の処理を行いたい場合、onBeforeRouteLeave は非常に役立つ composable です。コンポーネント単位でルートの離脱を検知し、遷移を制御できるため、ユーザーの操作を柔軟にハンドリングできます。
本記事では、公式ドキュメントの説明を補完し、実務での活用シーンや注意点を詳しく解説します。初〜中級者の方が理解しやすいように、具体例や落とし穴も交えて紹介します。
まず結論:onBeforeRouteLeave のポイント
- コンポーネントが破棄される直前にルート遷移を検知できる
- 遷移をキャンセルしたり、確認ダイアログを表示したりできる
- ページ単位ではなくコンポーネント単位で登録可能
- 非同期処理を挟んで遷移を制御できる(Promise 対応)
- Vue Router の
beforeRouteLeaveと同等の機能を Composition API で使える
いつ使うべきか・使わない方がよいケース
使うべきケース
- フォームの未保存データがある場合にユーザーに確認を促したい
- モーダルやダイアログを開いている状態で誤ってページ遷移するのを防ぎたい
- ページ離脱時に特定のクリーンアップ処理やログ送信を行いたい
- 複数のコンポーネントが混在するページで、それぞれ独立して遷移制御を行いたい
使わない方がよいケース
- グローバルにすべての遷移を制御したい場合(その場合は Nuxt のミドルウェアや Vue Router のグローバルガードを使う)
- 単純に遷移後の処理だけを行いたい場合(
onBeforeRouteLeaveは遷移前の制御が目的) - 過度に複雑なロジックを入れてしまうとユーザー体験が悪化する可能性がある
実務でよくあるユースケースとサンプルコード
1. フォームの未保存データを検知して確認ダイアログを表示
ユーザーが入力中のフォームを誤って離脱しないように警告を出す例です。
<script setup>
import { ref } from 'vue'
import { onBeforeRouteLeave } from '#app'
const isDirty = ref(false)
function onInput() {
isDirty.value = true
}
onBeforeRouteLeave((to, from, next) => {
if (isDirty.value) {
const answer = window.confirm('変更が保存されていません。ページを離れますか?')
if (answer) {
next()
} else {
next(false)
}
} else {
next()
}
})
</script>
<template>
<input type="text" @input="onInput" />
</template>
2. モーダルが開いているときは遷移をブロック
モーダルの状態に応じて遷移を制御し、誤操作を防止します。
<script setup>
import { ref } from 'vue'
import { onBeforeRouteLeave } from '#app'
const isModalOpen = ref(false)
onBeforeRouteLeave((to, from, next) => {
if (isModalOpen.value) {
alert('モーダルが開いているため、先に閉じてください。')
next(false)
} else {
next()
}
})
</script>
<template>
<button @click="isModalOpen = true">モーダルを開く</button>
<div v-if="isModalOpen">モーダルコンテンツ</div>
</template>
3. 非同期処理を挟んで遷移を制御(例:サーバーへの保存確認)
サーバーに保存処理を行い、その結果によって遷移を許可する例です。
import { onBeforeRouteLeave } from '#app'
async function saveData() {
// 疑似的な保存処理
return new Promise(resolve => setTimeout(() => resolve(true), 1000))
}
onBeforeRouteLeave(async (to, from, next) => {
const saved = await saveData()
if (saved) {
next()
} else {
alert('保存に失敗しました。遷移をキャンセルします。')
next(false)
}
})
よくある落とし穴・注意点
SSR と Hydration の影響
onBeforeRouteLeave はクライアントサイドでのみ動作します。サーバーサイドレンダリング(SSR)時には呼ばれないため、サーバーでの副作用を期待しないでください。
遷移キャンセル時の状態管理
遷移をキャンセルした場合、コンポーネントは破棄されません。状態をリセットしたり、UIを元に戻す処理は自分で実装する必要があります。
パフォーマンスへの配慮
複雑な非同期処理を遷移前に行うと、ユーザーの操作感が悪化します。処理はできるだけ軽量にし、必要に応じてローディング表示を検討しましょう。
複数コンポーネントでの競合
同じページ内で複数のコンポーネントが onBeforeRouteLeave を登録している場合、すべてのガードが実行されます。どのガードが遷移をキャンセルしているか把握しづらくなるため、設計時に整理が必要です。
まとめ
onBeforeRouteLeave は Nuxt でページ遷移前に細かい制御を行いたいときに非常に便利な機能です。フォームの未保存警告やモーダルの誤遷移防止など、ユーザー体験を向上させるために活用できます。
ただし、SSR では動作しないことや複数コンポーネントでの競合、非同期処理のパフォーマンス影響など注意点もあります。これらを理解した上で適切に使うことで、より良い Nuxt アプリケーションを構築できるでしょう。
onBeforeRouteLeave は Vue Router の beforeRouteLeave と同じ役割ですが、Composition API に最適化されているため、Nuxt 3 ではこちらの使用が推奨されます。
※このページは Nuxt.js 公式ドキュメントの翻訳ページです。
公式ドキュメントの該当ページはこちら:
https://nuxt.com/docs/3.x/api/utils/on-before-route-leave