理解导航守卫
导航就是我们所说的路由在发生变化,当路由发生变化的时候,我们想要做的事情,这就是导航守卫。关于导航守卫 我们一一介绍一下,在实际开发中用的也是比较多的。
全局前置守卫
全局守卫顾名思义,就是用来检测全局所有的路由变化,代码写在路由页面。
var loadingInstance = null;
var hasToken = store.state.token
router.beforeEach((to,from,next)=>{
/**
* 这里函数执行时候
* 1;可以获取地址变化信息
* 2:这里没有匹配到to地址的路由对象
* 3:没有加载【路由组件】
*/
// console.log(this);//没有this
// console.log('from-----',from)//变化前的信息
// console.log('to-----',to)//变化后的信息
// 这里做权限控制
if(to.meta.auth){
// 验证是否登录 如果登录 可以进入其他组件
// 验证userid 和token
if(!hasToken || hasToken == 'null' ){
// 表示没有登录---跳转到登录页面
//如果再次登录成功后 直接进入到权限页面
next('/home/login?redirect='+to.path)
}else{
// 表示已经登录
next()//放行
}
}else{
next()//非权限页面放行
}
})
//全局后置钩子 它和前置守卫不同的地方在于 不会接受next函数 也不会改变导航本身 所以后置钩子不用添加next()
router.afterEach(()=>{
loadingInstance.close()
})
需要注意的是,在使用前置导航守卫的时候,最后一定要执行next()这个是属于放行,否则的话 全局导航守卫是不生效的 但是也不会报错
全局导航守卫的方法
router.beforeEach((to,from,next)=>{
//
})
router.afterEach((to,from)=>{
//
})
参数:
- to:即将要进入的目标路由对象
- from:当前导航正要离开的路由
- next:在前置导航守卫中,一定要写next(),否则页面不会跳转页面
to,from返回值是一个对象 就是routes数组里面配置的某个具体的路由对象
比如:to.path to.name to.meta 【path,name,meta】这些字段都是自己在路由里面定义的字段。
路由独享守卫
你可以在路由配置上直接定义beforeEnter 守卫
就是将路由独享守卫写在我们某个具体的路由对象里面,
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
//这里的参数 与前置守卫的方法参数是一样的
}
}
]
})
组件内的守卫
这些钩子函数都是在路由组件内直接使用的
- beforRouteEnter
- beforeRouteUpdate
- beforeRouterLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
}
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
beforeRouteLeave (to, from, next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
完整的导航解析流程
- 导航被触发
- 在失活的组件里代用beforeRouteLeave守卫
- 调用全局的beforeEach守卫
- 在重用的组件里调用beforeRouteUpdate
- 在路由配置里调用beforeEnter
- 解析异步路由组件
- 在被激活的组件里调用beforeReolve守卫
- 调用全局的beforeResolve守卫
- 导航被确认
- 调用全局的afterEach钩子
- 触发DOM更新
- 调用beforeRouteENter守卫 传给next 的回调函数,创建好的组件实例 会作为回调函数的参数传入。