6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue Router v4 のナビゲーションガード:種類と使い方

Posted at

はじめに

編集中に画面遷移をしようとしたときに、「編集中の内容があるが保存せずに移動していいか」を確認するモーダルを出したいという場面に遭遇し、Vue Routerのナビゲーションガードを使用しました。

実装を進めるなかで、Vue Routerのナビゲーションガードの種類、それぞれの使用法を学んだのでまとめます。

ナビゲーションガードとは

Vue Routerのナビゲーションガードは、ルートの遷移前後の処理を制御できる仕組みです。
主に、リダイレクト(別ページに強制移動)やキャンセル(ページ遷移を中断し、現在のページにとどまる)によってルートの遷移を防ぐために使用されます。

Vue Router のナビゲーションガードはVue Routerの仕組みであるため、Vue Router を通じたルート遷移でのみ発火します。
そのため、<a>タグを直接用いた場合、通常のHTMLナビゲーションとして処理され、Vue Router のガードが適用されません。
Vue Router のガードを機能させるには、<router-link> や router.push() を使用する必要があります。

ナビゲーションガードの種類

Vue Routerには以下3種類のナビゲーションガードがあります。

  1. グローバルガード
  2. ルート単位ガード
  3. コンポーネント内ガード

それぞれについて説明します。

グローバルガード

グローバルガードはアプリ全体のルート遷移に対して適用されるガードです。
3種類あり、それぞれ実行されるタイミングが異なります。

  • beforeEach:ルート遷移前に実行
  • beforeResolve:すべてのコンポーネント内ガードと非同期のコンポーネント読み込み終了後に実行
  • afterEach:ルート遷移完了後に実行
const router = createRouter({ ... })

router.beforeEach((to, from) => {
  // ...
  // falseを返すことでナビゲーションをキャンセルできる
  return false
})

それぞれのガード関数は、以下2つの引数を受け取ります。
どちらもルートオブジェクトです。

  • to:遷移先のルート情報
  • from:現在のルート情報

以下の戻り値を設定できます。

  • false:ナビゲーション(ルート遷移)をキャンセルする
  • ルートロケーションオブジェクト:現在のナビゲーションをキャンセルし、router.push() のように新しいルートへの遷移を開始
router.beforeEach((to, from) => {
  if (!isAuthenticated && to.name !== 'Login') {
    return { name: 'Login' } // ログインページへリダイレクト
  }
})

第3引数 next について
Vue Routerの以前のバージョン(v3)では、nextという第3引数が用いられていましたが、v4では推奨されていません。しかし、現在も使用可能となっています。
nextを使用する書き方は、以下の公式ガイドを参照してください。

ルート単位ガード

ルート単位ガードは、グローバルガード (beforeEach)とは異なり、特定のルート に対して設定するガードです。

  • beforeEnter:特定のルート設定内で直接定義すると、そのルートに新しく入るときのみ実行される。
    ただし、同じルートで params だけが変更される場合(例: /users/1 → /users/2)は発火しない。

以下の例では、ユーザーが /users/1 や /users/2 などにアクセスしようとするとナビゲーションがキャンセルされます。

const routes = [
  {
    path: '/users/:id', // 例: /users/1、 /users/2 など
    component: UserDetails,
    beforeEnter: (to, from) => {
      // ナビゲーションをキャンセル
      return false
    },
  },
]

コンポーネント内ガード

コンポーネント内ガードは、各コンポーネント内で定義するガードです。
特定のコンポーネントが表示・更新・削除されるときに処理を実行することができます。
コンポーネント内ガードは以下の3種類あります。

  • beforeRouteEnter
    コンポーネントが表示される前に実行
    コンポーネントが作成される前なので、this(コンポーネントのインスタンス)にはアクセスできない
  • beforeRouteUpdate
    コンポーネントが再利用されるとき(同じコンポーネントが使われたまま、URL のパラメータが変わったとき)に実行
    例: /users/1 → /users/2 への遷移
  • beforeRouteLeave
    コンポーネントから離れる前(異なるページに遷移するとき)に実行
    ページを離れる前に確認メッセージを出すときに使用される
<script>
export default {
  beforeRouteEnter(to, from) {
    //...
  },
  beforeRouteUpdate(to, from) {
    //...
  },
  beforeRouteLeave(to, from) {
    //...
  }
}
</script>

上記はOptionsAPIの書き方です。
Composition APIの場合は、以下を参照してください。

最後に

「編集中の内容があるが保存せずに移動していいか」を確認するモーダルを出したかったので、今回は beforeRouteLeaveのみを使用しましたが、これを機に初めてナビゲーションガードを学習することができました。

公式のドキュメントは英語で書かれていたり、難しかったりして避けてしまいがちでしたが、最新の情報を得るためには、公式ガイドを活用することが重要だと実感しました。

最後までお読みいただきありがとうございました!

参考

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?