導(dǎo)航守衛(wèi)其實(shí)也是路由守衛(wèi),也可以是路由攔截(JAVA中的過(guò)濾器, Django,ThinkPHP中的中間件),我們可以通過(guò)路由攔截,來(lái)判斷用戶是否登錄,該頁(yè)面用戶是否有權(quán)限瀏覽,需要結(jié)合meta來(lái)實(shí)現(xiàn)
vue中路由守衛(wèi)一共有三種,一個(gè)全局路由守衛(wèi),一個(gè)是組件內(nèi)路由守衛(wèi),一個(gè)是router獨(dú)享守衛(wèi)
所謂的路由守衛(wèi)可以簡(jiǎn)單的理解為一座房子的門口的保安,想要進(jìn)入這個(gè)房子就必須通過(guò)保安的檢查,要告訴路由守衛(wèi)你從哪里來(lái)?總不能隨便陌生人就給放進(jìn)去?要到哪里去?然后保安再告訴你下一步該怎么做?如果你的確是這個(gè)房子主人允許進(jìn)入的人,那就讓你進(jìn)入,否則就要打電話給房子主人,跟房主商量(登錄注冊(cè)),給你權(quán)限。
// 通過(guò)這個(gè)匹配判斷是否有該權(quán)限或要求,這個(gè)一般作為頁(yè)面權(quán)限設(shè)置,比如哪些頁(yè)面需要登錄才能進(jìn)入,哪些不需要 to.matched.some(res => res.meta.requireAuth)
一、全局路由守衛(wèi)
所謂全局路由守衛(wèi),就是小區(qū)大門,整個(gè)小區(qū)就這一個(gè)大門,你想要進(jìn)入其中任何一個(gè)房子,都需要經(jīng)過(guò)這個(gè)大門的檢查
全局路由守衛(wèi)有個(gè)兩個(gè):一個(gè)是全局前置守衛(wèi),一個(gè)是全局后置守衛(wèi)
router.beforeEach((to, from, next) => { console.log(to) => // 到哪個(gè)頁(yè)面去? console.log(from) => // 從哪個(gè)頁(yè)面來(lái)? next() => // 一個(gè)回調(diào)函數(shù) } router.afterEach(to,from) = {}
next():回調(diào)函數(shù)參數(shù)配置
next(false): 中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了 (可能是用戶手動(dòng)或者瀏覽器后退按鈕),那么 URL 地址會(huì)重置到 from 路由對(duì)應(yīng)的地址
next('/') 或者 next({ path: '/' }): 跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個(gè)新的導(dǎo)航。你可以向 next 傳遞任意位置對(duì)象,且允許設(shè)置諸如 replace: true、name: 'home' 之類的選項(xiàng)以及任何用在 router-link 的 to prop 或 router.push 中的選項(xiàng)
二、組件路由守衛(wèi)
// 跟methods: {}等同級(jí)別書寫,組件路由守衛(wèi)是寫在每個(gè)單獨(dú)的vue文件里面的路由守衛(wèi) beforeRouteEnter (to, from, next) { // 注意,在路由進(jìn)入之前,組件實(shí)例還未渲染,所以無(wú)法獲取this實(shí)例,只能通過(guò)vm來(lái)訪問(wèn)組件實(shí)例 next(vm => {}) } beforeRouteUpdate (to, from, next) { // 同一頁(yè)面,刷新不同數(shù)據(jù)時(shí)調(diào)用, } beforeRouteLeave (to, from, next) { // 離開當(dāng)前路由頁(yè)面時(shí)調(diào)用 }
三、路由獨(dú)享守衛(wèi)
路由獨(dú)享守衛(wèi)是在路由配置頁(yè)面單獨(dú)給路由配置的一個(gè)守衛(wèi)
export default new VueRouter({ routes: [ { path: '/', name: 'home', component: 'Home', beforeEnter: (to, from, next) => { // ... } } ] })
vue-router提供了導(dǎo)航鉤子:全局前置導(dǎo)航鉤子 beforeEach和全局后置導(dǎo)航鉤子 afterEach,他們會(huì)在路由即將改變前和改變后進(jìn)行觸發(fā)。所以判斷用戶是否登錄需要在beforeEach導(dǎo)航鉤子中進(jìn)行判斷。
導(dǎo)航鉤子有3個(gè)參數(shù):
1、to:即將要進(jìn)入的目標(biāo)路由對(duì)象;
2、from:當(dāng)前導(dǎo)航即將要離開的路由對(duì)象;
3、next :調(diào)用該方法后,才能進(jìn)入下一個(gè)鉤子函數(shù)(afterEach)。
next()//直接進(jìn)to 所指路由
next(false) //中斷當(dāng)前路由
next('route') //跳轉(zhuǎn)指定路由
next('error') //跳轉(zhuǎn)錯(cuò)誤路由
beforeEach:
路由配置文件:
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import HomePage from '@/pages/home.vue' Vue.use(Router) const router=new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, { path: '/home', name: 'home', component: HomePage }, { path:'*', redirect:'/home' } ], }) router.beforeEach((to,from,next)=>{ console.log(to); console.log(from); next(); }) export default router;
打印結(jié)果如下:
實(shí)現(xiàn)用戶驗(yàn)證的代碼:
router.beforeEach((to, from, next) => { //我在這里模仿了一個(gè)獲取用戶信息的方法 let isLogin = window.sessionStorage.getItem('userInfo'); if (isLogin) { //如果用戶信息存在則往下執(zhí)行。 next() } else { //如果用戶token不存在則跳轉(zhuǎn)到login頁(yè)面 if (to.path === '/login') { next() } else { next('/login') } } })
afterEach:
和beforeEach不同的是afterEach不接收第三個(gè)參數(shù) next 函數(shù),也不會(huì)改變導(dǎo)航本身,一般beforeEach用的最多,afterEach用的少.
router.afterEach((to,from)=>{ //這里不接收next console.log(to); console.log(from); })