在開發webApp的時候,考慮到用戶體驗,常常會把不須要調用我的數據的頁面設置成遊客能夠訪問,而當用戶進入到一些須要我的數據的,例如購物車,我的中心,個人錢包等等,在進行登陸的驗證判斷,若是判斷已經登陸,則顯示頁面,若是判斷未登陸,則直接跳轉到登陸頁面提示用戶登陸,今天就來分享下如何使用vue-router的beforEach方法來實現這個需求。vue
本篇文章默認您已經會使用webpack
或者vue-cli
來進行環境的搭建,而且具備必定的vue基礎,若是您目前是一個新手,那麼網上搜索一下就好,相關文章很是多,這裏就再也不贅述了。 話很少說,直接上代碼。 爲了方便往後代碼的可維護性,我把相關方法寫在了一個新建的filter.js文件裏webpack
接下來進入filter.js文件中,首先引入vue-router:import router from "./router";
而後咱們使用router.beforEach
方法:ios
router.beforeEach((to, from, next) => {
//根據字段判斷是否路由過濾
if (to.matched.some(record => record.meta.auth)) {
if (getToken() !== null) {
next()
} else {
//防止無限循環
if (to.name === 'login') {
next();
return
}
next({
path: '/login',
});
}
} else {
next()//若點擊的是不須要驗證的頁面,則進行正常的路由跳轉
}
});
複製代碼
beforEach實際上是vur-router的鉤子函數,能夠理解爲每一個router跳轉以前都會調用的一個方法,既然有before同理固然也有afterEach,這個咱們之後再講。web
首先來解釋下beforEach的三個參數:vue-router
next()
: 進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是 confirmed (確認的)。next(false)
: 中斷當前的導航。若是瀏覽器的 URL 改變了(多是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。next(error)
: (2.4.0+) 若是傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回調。好了,看到這裏可能有些人仍是沒有理解,不要緊,接下來我舉個例子就能夠明白了。
假設咱們目前有三個路由:/home,/mine,/login
咱們初始進入爲/home
,這時候點擊跳轉/mine
,可是因爲咱們沒有登陸,因此會自動跳轉到/login
在以上這種狀況下,
to:表明着路由/mine
,咱們要進入的路由。
from:表明着路由/home
,咱們將要離開的路由。
注意,使用beforEach最後必需要調用next()
,不然會報錯,若是不傳參數,咱們就會成功進入到/mine
,若是咱們傳遞參數,例如next('/login')
,那麼咱們在點擊任何路由都會跳轉到/login
界面。
可是咱們的需求是隻有點擊須要進行登陸驗證的頁面才進行攔截跳轉,所以,咱們須要加一些判斷條件來進行路由的篩選。vue-cli
if (to.matched.some(record => record.meta.auth)) {
if (getToken() !== null) {
next()
}
}
複製代碼
這裏的to就是上面講的參數to,to.matched
是一個對象數組,裏面有to指向路由的相關信息,例如:path,name,meta等等。
咱們用該數組調用some()方法根據返回值true
或者false
來進行判斷,因此咱們要在router.js路由配置文件中爲咱們須要驗證登陸判斷跳轉的路由添加一個字段來做爲判斷條件axios
{
path: '/mine',
name: 'mine',
component: mine,
meta:{auth:true} //咱們本身添加的字段
}
複製代碼
因爲給路由添加了meta:{auth:true}
,因此咱們的to.matched.some(record => record.meta.auth)
會返回true
,這時咱們就能夠作登陸判斷了,個人項目是經過把token存入到localstorage
來進行判斷的, getToken()是我封裝的一個獲取localstorage
方法。後端
if (getToken() !== null) {
next()//若token不爲null,則進行路由跳轉
}
複製代碼
若是沒有token,咱們下一步繼續進行判斷,也就是最終目的,進行路由攔截,跳轉到登陸頁數組
else {
next({
path: '/login',
});
}
複製代碼
可是這時候咱們會遇到新的問題,打開控制檯會發現路由會無限的循環並最終崩潰,這是什麼緣由呢?仔細閱讀上文紅色加粗,咱們能夠理解爲瀏覽器
next()
表示路由成功,直接進入to路由,不會再次調用router.beforeEach()next({ path: '/login', });
表示路由攔截成功,重定向至login,會再次調用router.beforeEach()也就是說beforeEach()必須調用next(),不然就會出現無限循環
next() 和 next('xxx') 是不同的,區別就是前者不會再次調用router.beforeEach(),後者會。而因爲咱們沒有token,因此在從新調用router.beforeEach()後,會再次進入到
else {
next({
path: '/login',
});
}
複製代碼
因此形成了無限循環,解決這個問題的方法也很簡單,咱們在next({ path: '/login', });
以前增長一個判斷條件
if (to.name === 'login') {
next();
return
}
複製代碼
若是咱們to的定向路由name == 'login'
,則執行next();
並return終止代碼運行。
以上就是經過router.beforEach方法進行路由攔截了,咱們不只僅能夠只作登陸判斷,經過這個方法能夠實現不少需求,只要是有關路由跳轉的均可以,在下只是拋磚引玉,若是有哪裏不對的地方或者有更好的方法能夠直接在評論告訴我,很是感謝。
2018.7.2
因爲實際項目中不少界面都須要進行token的驗證攔截,所以考慮後決定把過濾的方法設置在axios攔截器的http response 攔截器
裏,根據後端返回的錯誤碼來判斷是token過時或者無效之類的錯誤來進行跳轉到登陸頁面.