vue 全局前置守衛引起死循環的原因與解決方法
- 2020 年 1 月 27 日
- 筆記
我們經常會用到全局前置守衛,如判斷用戶有沒有登陸過,如果登陸過就直接跳到目的頁面,如果沒有登陸過,就跳轉到登陸頁。
先看官網對全局前置守衛的介紹
使用 router.beforeEach 註冊一個全局前置守衛:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
當一個導航觸發時,全局前置守衛按照創建順序調用。守衛是非同步解析執行,此時導航在所有守衛 resolve 完之前一直處於 等待中。
每個守衛方法接收三個參數:
-
to: Route
: 即將要進入的目標 路由對象 -
from: Route
: 當前導航正要離開的路由 -
next: Function
: 一定要調用該方法來 resolve 這個鉤子。執行效果依賴next
方法的調用參數。-
next()
: 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。 -
next(false)
: 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到from
路由對應的地址。 -
next('/')
或者next({ path: '/' })
: 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向next
傳遞任意位置對象,且允許設置諸如replace: true
、name: '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 鉤子函數。