takeda_san’s blog

KotlinとVRを頑張っていく方向。

Vue Routerのナビゲーションガード(beforeEach)が2回発火している気がする

現象

f:id:takeda_san:20190418213449g:plain

入力フォームの画面で、編集途中で画面遷移するときに保存しますか?みたいなダイアログ出しますよね。
Vue RouterだとナビゲーションガードのbeforeEachを使うと、お手軽に実装出来て楽ですね。

ナビゲーションガード | Vue Router

こんなの。

  beforeRouteLeave: function(to, from, next) {
    console.log("beforeRouteLeaveが実行されました");
    window.confirm("保存しよ?");
    next();
  }

ですが、御覧の通りダイアログが2つ出るんですよ…

vue 2.6.10  
vue-router 3.0.3  

原因

バグでした…

`beforeRouteLeave` invoked twice when redirecting inside of beforeRouteEnter · Issue #2102 · vuejs/vue-router · GitHub

beforeEach使ってると再現するっぽい。
よくrouter.jsとかで認証状態を遷移ごとにチェックするときに、こんなコードを書くと思うのですよね。

router.beforeEach((to, from, next) => {
  // ホントならここで認証情報を取得する
  const isAuth = false;
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth);

  if (isAuth) {
    // 認証状態はそのまま遷移
    next();
  } else if (requiresAuth) {
    // 認証してないのでログイン画面へ
    next({
      path: "/login",
      query: { redirect: to.fullPath }
    });
  } else {
    // 認証が必要ないのでそのまま遷移
    next();
  }
});

確かに気持ちは分かるが、発火するのは1回がいいよね…

対処

1回目でダイアログを出すフラグを折って、2回目が発火してもダイアログを出さないようにしました。
無理やりすぎて、何かすがすがしいよね。

コードはここ。

github.com