vue-router

304 阅读2分钟

1.导航钩子

a.全局的导航

前置守卫,后置钩子

const router = new VueRouter({...})
router.beforeEach((to,from,next)=>{
    // do
})

后置钩子

router.afterEach((to,from)=>{
    // do
})

参数: to,from,next

1.to: Route, 代表要进入的目标, 是一个路由对象

2.from:Route,代表当前正要离开的路由,同样是一个路由对象

3.next:Function,这是一个必须调用的方法,具体的执行结果依赖next方法调用的参数

next方法必须要调用,否则钩子函数不会resolved

next()
// 进入管道中的下一个钩子,如果全部钩子执行完了,则导航的状态就是confirmed(确认)状态
next(false)
// 代表中断掉当前的导航,即不会进入to代表的路由对象,此时该URL的地址会被重置到from对象相对应的路由地址
next("/") 和next({path:"/"}) 
// 在中断掉当前导航的同时,跳转到指定的路由地址
next(error)
// 如果传入参数是一个Error实例,导航被终止的同时会将错误传递给router.onError() 的回调中

b.路由独享的钩子

单个路由独享的导航钩子,它是在路由配置上直接进行定义的

const router = new VueRouter({
    routes:[
        {
            path:'/',
            component: File,
            beforeEnter:(to,from,next)=>{
                // do...
            }
        }
    ]
})

参数和前置守卫是一样的,规则也是一样的next函数必须要调用

c. 组件内的导航钩子

组件内的导航钩子主要有三种:beforeRouteEnter、beforeRouteUpdate、beforeRoute Leave

<template></template>
<script>
    export default{
        data(){
            retrun{}
        },
        beforeRouteEnter(to, from, next){
            // do...
            next((vm)=>{
                // 通过vm来访问组件实例 可以解决this访问不到
            })
        },
        beforeRouteUpdate(to, from, next){
            // do...
        },
        beforeRouteLeave(to, from, next){
            // do...
        }
    }
</script>

beforeRouteEnter 不能获取组件实例this, 因为当该守卫执行时,组件实例还没有被创建出来,剩下的两个钩子可以正常获取组件实例this

beforeRoute Enter支持给next传递回调,其他两个不支持

完整的导航解析流程

// 1. 导航被触发
// 2. 在失活的组件里调用 beforeRoueLeave 守卫
// 3. 调用全局的 beforeEach 守卫
// 4. 在重用的组件里调用beforeRouteUpdate 守卫
// 5. 在路由配置里调用 beforeEnter 
// 6. 解析异步路由组件
// 7. 在被激活的组件里调用 beforeRouteEnter
// 8. 调用全局的 beforeResolve 守卫
// 9. 导航被确认
// 10. 调用全局的afterEach钩子
// 11. 触发DOM更新
// 12. 用创建好的实例调用beforeRouteEnter 守卫中传给next的回调函数

使用route钩子实现登录拦截

const router = new VueRouter({
    routes:[
        {
            path:'/login',
            component:Login
        },
        {
            path:'/mine',
            component:Mine,
            meta:{
                requiredAuth:true
            }
        }
    ]
})

router.beforeEach((to, from, next)=>{
    to.matched.some((route)=>{
        if(route.meta && route.meta.requiredAuth){
            if(!sessionStorage.getItem('token')){
                next({path:'/login'})
            }else{
                next()
            }
        }else{
            next()
        }
    })
})