[vue-router] BeforeRouteLeave가 두 번 발화

TL;DR


  • Vue-RouterBeforeRouteLeave 등 네비게이션 가드가 두 번 발화하는 경우가 있다.
  • 트랜지션 컴퍼넌트에 어떠한 리디렉션이 있을 때 발생합니다.
  • to 를 조사하는 것으로 회피 가능.

  • 같은 문제를 다룬 이슈
    => htps : // 기주 b. 코 m/ゔ에 js/ゔ에-로테 r/이스에 s/2102

    본건은 사양으로서 취급되는 것 같기 때문에, 향후 잠시 대응될 전망은 없을 것 같다.

    재현 환경


  • Chrome 버전: 75.0.3770.142
  • Nuxt 2.6
  • vue-router 3.0

  • 리포지토리 및 검증 동영상



    htps : // 기주 b. 코 m / 이코 - 오타 / 인 ぉ


    톱 페이지 - 페이지 1 - 페이지 2라는 구성으로,
  • 페이지 2의 뒤로 버튼을 누르면 window.confirm()가 표시됩니다. 「OK」를 누르면 페이지 1로 천이한다.
  • 1 페이지에서 2 페이지의 전환을 잡으면 톱 페이지로 건너 뜁니다.

    상정으로서는, 예를 들면 상품 판매 사이트에 있어서, 페이지 2가 주문 완료 화면이고, 페이지 1이 결제 확인 페이지, 정도일 때.
    그러나 이때 페이지 2의 BeforeRouteLeave가 두 번 발화한다. window.confirm() OK를 한 번 눌러도 대화 상자가 다시 나타납니다.

    어떻게 일어나는가?



    예상





    2 => 1, 1 => top과 같은 전이를 할 것 같다.

    실제




    실제 페이지 2의 beforeRouteLeave 는 이와 같이 거동한다.
    beforeRouteLeave 가 2=>1 과 2 => top 의 2회분 불린다. 인수의 from.nameto.name 의 내용을 조사하면 확실히 그렇게 되어 있다. 1 => top으로의 리디렉션은이 두 번째 전환을 유발합니다. 이때 1=>top의 천이도 아니다! 어디까지나 from="2", to="top"의 beforeRouteLeave 가 달린다!

    해결책


    ページ2beforeRouteLeaveto 를 검사하여 첫 번째 전이에 대해 가드하지 않도록 하면 된다.

    before


      beforeRouteLeave(to, from, next) {
        window.confirm("このページを離れますか?") ? next() : next(false);
      }
    

    after


      beforeRouteLeave(to, from, next) {
        if (to.name === "first") {
          next();
          return;
        }
    
        window.confirm("このページを離れますか?") ? next() : next(false);
      }
    

    덧붙여 after는 가독성이 낮은 코드이므로(일견 「뒤로」의 때에는 가드 하지 않는다, 라고 하는 코드로 보인다) 공식 issue등을 인용해 적절히 코멘트에 추기하는 것을 추천한다.
  • 좋은 웹페이지 즐겨찾기