路由跳轉(zhuǎn)前做一些驗(yàn)證型将,比如登錄驗(yàn)證,是網(wǎng)站中的普遍需求。
對(duì)此,vue-route 提供的 beforeRouteUpdate 可以方便地實(shí)現(xiàn)導(dǎo)航守衛(wèi)(navigation-guards)琴锭。
在一個(gè)網(wǎng)站中,訪問除了登錄以外的接口往往都需要驗(yàn)證用戶的個(gè)人信息衙传,由于后臺(tái)的登錄信息在一定的時(shí)間后會(huì)失效决帖,這個(gè)時(shí)候我們?cè)谔D(zhuǎn)頁(yè)面的時(shí)候再訪問別的接口的時(shí)候,由于沒有登錄信息可能導(dǎo)致接口報(bào)錯(cuò)蓖捶。一般我們會(huì)在vue組件的beforeCreate周期中寫一個(gè)驗(yàn)證登錄信息接口地回,以驗(yàn)證用戶信息是否失效。
事實(shí)上上面的操作并沒有什么軟用俊鱼,之前在vue生命周期和異步加載的關(guān)系一文中就指出了異步操作是獨(dú)立于生命周期之外的操作刻像,因此vue并不會(huì)乖乖的先執(zhí)行完beforeCreate周期中的異步操作,驗(yàn)證了信息后再執(zhí)行下一周期并闲,而是先執(zhí)行完整個(gè)生命周期再執(zhí)行異步操作细睡,這樣的做法會(huì)導(dǎo)致,vue實(shí)例在渲染dom的時(shí)候由于大量數(shù)據(jù)得不到焙蚓,渲染出一個(gè)很丑的頁(yè)面纹冤,直到驗(yàn)證登陸信息接口訪問完畢洒宝,才能返回登錄頁(yè)购公。不僅如此,由于異步操作的執(zhí)行時(shí)間不定雁歌,還可能出現(xiàn)大量的頁(yè)面報(bào)錯(cuò)宏浩,總之,這么做可以靠瞎,但體驗(yàn)很差比庄。
vue-router提供了導(dǎo)航守衛(wèi)求妹,幫助我們解決一些在組件加載之前,可以做一些操作佳窑,尤其是異步操作制恍,這樣可以避免組件加載完畢后,卻沒有數(shù)據(jù)的尷尬神凑。當(dāng)然净神,你不應(yīng)該在組件加載之前做太多的異步操作,這樣會(huì)導(dǎo)致頁(yè)面的白屏?xí)r間過長(zhǎng)溉委,用戶體驗(yàn)也很差鹃唯,所以,須慎用導(dǎo)航守衛(wèi)瓣喊。
下面寫一個(gè)例子:
列舉需要判斷登錄狀態(tài)的“路由集合”坡慌,當(dāng)跳轉(zhuǎn)至集合中的路由時(shí),如果“未登錄狀態(tài)”藻三,則跳轉(zhuǎn)到登錄頁(yè)面LoginPage洪橘;
當(dāng)直接進(jìn)入登錄頁(yè)面LoginPage時(shí),如果“已登錄狀態(tài)”棵帽,則跳轉(zhuǎn)到首頁(yè)HomePage梨树;
import Vue from 'vue';
import Router from 'vue-router';
import LoginPage from '@/pages/login';
import HomePage from '@/pages/home';
import GoodsListPage from '@/pages/good-list';
import GoodsDetailPage from '@/pages/good-detail';
import CartPage from '@/pages/cart';
import ProfilePage from '@/pages/profile';
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/', // 默認(rèn)進(jìn)入路由
redirect: '/home' //重定向
},
{
path: '/login',
name: 'login',
component: LoginPage
},
{
path: '/home',
name: 'home',
component: HomePage
},
{
path: '/good-list',
name: 'good-list',
component: GoodsListPage
},
{
path: '/good-detail',
name: 'good-detail',
component: GoodsDetailPage
},
{
path: '/cart',
name: 'cart',
component: CartPage
},
{
path: '/profile',
name: 'profile',
component: ProfilePage
},
{
path: '**', // 錯(cuò)誤路由
redirect: '/home' //重定向
},
]
});
// 全局路由守衛(wèi)
router.beforeEach((to, from, next) => {
console.log('navigation-guards');
// to: Route: 即將要進(jìn)入的目標(biāo) 路由對(duì)象
// from: Route: 當(dāng)前導(dǎo)航正要離開的路由
// next: Function: 一定要調(diào)用該方法來(lái) resolve 這個(gè)鉤子。執(zhí)行效果依賴 next 方法的調(diào)用參數(shù)岖寞。
const nextRoute = ['home', 'good-list', 'good-detail', 'cart', 'profile'];
let isLogin = global.isLogin; // 是否登錄
// 未登錄狀態(tài)抡四;當(dāng)路由到nextRoute指定頁(yè)時(shí),跳轉(zhuǎn)至login
if (nextRoute.indexOf(to.name) >= 0) {
if (!isLogin) {
console.log('what fuck');
router.push({ name: 'login' })
}
}
// 已登錄狀態(tài)仗谆;當(dāng)路由到login時(shí)指巡,跳轉(zhuǎn)至home
if (to.name === 'login') {
if (isLogin) {
router.push({ name: 'home' });
}
}
next();
});
export default router;
這是Vue官方文檔中對(duì)導(dǎo)航守衛(wèi)的定義
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB
分別寫了一下5種守衛(wèi):
- 全局前置守衛(wèi)
- 全局解析守衛(wèi)
- 全局后置鉤子
- 路由獨(dú)享的守衛(wèi)
- 組件內(nèi)的守衛(wèi)
完整的導(dǎo)航解析流程
- 導(dǎo)航被觸發(fā)。
- 在失活的組件里調(diào)用離開守衛(wèi)隶垮。
- 調(diào)用全局的 beforeEach 守衛(wèi)藻雪。
- 在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi) (2.2+)。
- 在路由配置里調(diào)用 beforeEnter狸吞。
- 解析異步路由組件勉耀。
- 在被激活的組件里調(diào)用 beforeRouteEnter。
- 調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)蹋偏。
- 導(dǎo)航被確認(rèn)便斥。
- 調(diào)用全局的 afterEach 鉤子。
- 觸發(fā) DOM 更新威始。
- 用創(chuàng)建好的實(shí)例調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)枢纠。