brand logo

ドキュメント

onBeforeRouteLeave

onBeforeRouteLeave composable は、コンポーネント内でルートガードを登録することを可能にします。

こちらも参照 Vue Router ドキュメント

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 ではこちらの使用が推奨されます。