vue-routerのナビゲーションガードを使う
はじめに
この記事は Treasure Advent Calender 2019 16日目の記事です。 大幅に遅刻(2回目)して大変申し訳ありません。
今回は、12/24 のクリスマスイブに行った、未来大 x 会津大 対バンLT会 で扱ったネタを書いていこうと思います。
はじめていきます。
今回簡単なテストアプリのリポジトリはこちらです。
やりたいこと
認証が必要なAPIを使用している際、 session token
が切れていた時に、/login
に飛ばしたい。
アプリ構成としては以下な感じです。
各PageComponentのcreatedで、vuexのactionをdispatchし結果をstateにcommit、
Pageの生成時にstateの値を参照するという流れです。
今回はコンポーネントの greet:
の後の文章を非同期で生成しています。
とりあえずtokenが有効かどうかを調べる isValidToken
APIを生やしてもらいました。
solution1
方法
App.vue の created
で、isValidToken
を呼び、無効だったら /login
に飛ばす。
結果
目的だった tokenが無効なら /login
に飛ばす という処理はできたのですが、isValidToken
関数が非同期通信をしているため、tokenが無効というのが返ってきてから/login
へ飛ばす処理の前にComponentのインスタンスが作られ、createdで呼んでいたAPIでのエラーが表示されていました。
図としては以下の感じ。
solution2
方法
vue-routerの グローバルビフォーガード を使う。
グローバルビフォーガードとは
いつナビゲーションがトリガーされようとも、グローバル before ガードは作られた順番で呼び出されます。ガードは非同期に解決されるかもしれません。そしてそのナビゲーションは全てのフックが解決されるまで 未解決状態 として扱われます。
全てのフックが解決されるまで未解決状態として扱われます
つまり非同期に解決されたとしてもインスタンスが作られず /login
に飛ばせます。
ただし、この場合ナビゲーションがトリガー毎にリクエストを飛ばすのでパフォーマンス重視のアプリならやらない方がいいのかもしません。
追加したコード
const router = new VueRouter({ routes }); router.beforeEach((to, from, next) => { if (!store.state.isLoggedIn && to.path != '/login') { next('/login'); } next(); });
※ 最初っからこっち使えよってわかるんですが↑の時は知りませんでした。無知の知!
結果
うまくいきました〜
おわりに
vue-routerのナビゲーションガードを使った場合、APIでの認証系エラーを表示せずログイン画面に遷移することができるようになりました。 しかし、ブログの途中でも言及しましたがこの方法だと画面遷移毎にリクエストを飛ばす必要があるためパフォーマンスを考えるとそんなよくなかったりするかも?
もしもっといい方法があったら教えてもらえると嬉しいです 🙇♀️
そしてTreasure2019のみなさん、アドカレ超遅刻してしまい申し訳ありませんでした。 迷惑かけた人には土下座するのでTreasureN次回誘ってください。