vue 全局前置守衛引發死循環的緣由與解決方法

咱們常常會用到全局前置守衛,如判斷用戶有沒有登錄過,若是登錄過就直接跳到目的頁面,若是沒有登錄過,就跳轉到登錄頁。javascript

先看官網對全局前置守衛的介紹vue

使用 router.beforeEach 註冊一個全局前置守衛:java

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

當一個導航觸發時,全局前置守衛按照建立順序調用。守衛是異步解析執行,此時導航在全部守衛 resolve 完以前一直處於 等待中api

每一個守衛方法接收三個參數:瀏覽器

  • to: Route: 即將要進入的目標 路由對象session

  • from: Route: 當前導航正要離開的路由異步

  • next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。函數

    • next(): 進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是 confirmed (確認的)。spa

    • next(false): 中斷當前的導航。若是瀏覽器的 URL 改變了 (多是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。code

    • next('/') 或者 next({ path: '/' }): 跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航。你能夠向 next 傳遞任意位置對象,且容許設置諸如 replace: truename: 'home' 之類的選項以及任何用在 router-link  to prop  router.push 中的選項。

    • next(error): (2.4.0+) 若是傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回調。

確保要調用 next 方法,不然鉤子就不會被 resolved  

回到咱們剛纔所說驗證登錄使用全局前置守衛

router.beforeEach((to,from,next) =>{
  if (sessionStorage.getItem("token")) {
     if(to.path === "/login"){
       next({path:"/dashboard"})
     }
     else{
       alert("1")
       next()
     }     
  }else{
    next({path: "/login"})   // 會再次執行前置導航守衛,由於路徑變化
  }
})

上面的代碼表面看沒有問題,

若是sessionStorage有token,而且若是即將要進入的目標路徑是登錄頁,就跳轉到/dashboard頁,若是是其它的頁面,就進入

若是sessionStorage沒有token 就進入登錄頁

可是代碼執行會引發死循環,緣由是沒有出口,執行next({path: "/login"})會再次執行全局前置導航守衛 

代碼改爲下面的就正常了

router.beforeEach((to, from, next) => {
  let token = window.sessionStorage.getItem('token');
  if (to.path != '/login' && !token) {
    next({
      path: '/login'
    })
  } else {
    if (to.path == '/login' && token) {
      next('/dashboard')
    } else {     
      next()
    }
  }
})

總結:執行next({ path: '/xxx' }) 跳到不一樣的地址都會再次執行 router.beforeEach 鉤子函數。

相關文章
相關標籤/搜索