ナビゲーションガード
- クリック後にコンポーネントが切り替わる間に処理を実行できる機能。
- ライフサイクルフックのようなイメージ
3つの書き方
グローバルコンポーネントビフォーガード
- 全てのルートに適用される。
- 認証系の手続きで使う事がある。
- routerのインスタンスに直挿
router/index.js
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
ルート単位ガード
- 直接ルート設定オブジェクトの
beforeEnter
ガードを定義することができます。
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
コンポーネント内ガード
-
ルートコンポーネント(ルータ設定に渡されるもの)の内側でルートナビゲーションガードを直接定義する
-
beforeRouteEnter
-
beforeRouteUpdate (2.2 で追加)
-
beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter(to, from, next) {
// このコンポーネントを描画するルートが確立する前に呼ばれます。
// `this` でのこのコンポーネントへのアクセスはできません。
// なぜならばこのガードが呼び出される時にまだ作られていないからです!
},
beforeRouteUpdate(to, from, next) {
// このコンポーネントを描画するルートが変更されたときに呼び出されますが、
// このコンポーネントは新しいルートで再利用されます。
// たとえば、動的な引数 `/foo/:id` を持つルートの場合、`/foo/1` と `/foo/2` の間を移動すると、
// 同じ `Foo` コンポーネントインスタンスが再利用され、そのときにこのフックが呼び出されます。
// `this` でコンポーネントインスタンスにアクセスできます。
},
beforeRouteLeave(to, from, next) {
//ページ遷移するときなど
}
}
beroreTouteLeaveを使用したcase
- ページを離れる時に「本当にこのページを離れますか?」という確認をユーザーに即すときなどに使う。
some.vue
/*
.
省略
*/
<script>
export default {
name:'About',
beforeRouteLeave(to, form, next){
const checkLeave = window.confirm('本当にこのページを離れますか?')
if(checkLeave){
next()
}else {
next(false)
}
}
</script>
to, from, nextとは
- to :Routeオブジェクト
- 新しい遷移先のオブジェクトを返す。
- from: Routeオブジェクト
- 遷移前のオブジェクトを返す。
- next: Function
- ナビゲーションガードの最後にnext()関数を呼び出す。
- next()関数を呼ばないと、コンポーネント間のパイプラインが終了できない。
- 結果として描画されないようになる。
- next()の引数
- next()
- 処理のパイプラインが完了し次のフックに移動する。
- next(false)
- 現在のナビゲーションを終了させ、ブラウザのurlが変化した場合はfromルートに戻る。
- next('/') or next({path: '/'})
- 現在のナビゲーションが終了。
- 任意のロケーションをnextに以下のようにセットできる。
- replace: true
- name: 'home'
- router-link
- toプロパティ
- router.pushで使用される任意のオプション
- next(error)
- ナビゲーションは中止
- 引数に渡されたものがErrorインスタンスの場合
error.onError()
を介して登録されたコールバック関数が渡される。
- next()
- next()関数は一度だけ呼ばれるようにする。
- 2回呼ばれる場合はerrorになる。
- 2回呼ばれるようなコードの書き方
// 2回呼ばれる悪いケース
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
// ユーザーが認証されていない場合、 `next` は2回呼ばれる
next()
})
// 修正したコード
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})