一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 18 天,点击查看活动详情。
导航守卫
如果在路由跳转过程中,想要改变跳转地址或取消跳转时,就要用到导航守卫了。
守卫分为:全局守卫, 单个路由独享的, 或者组件级的
全局守卫
1、beforeEach
全局前置守卫
所有路由都会经过它把关,在这里可以拦截处理用户是否有访问页面的权限
接收三个参数:
- to: 目标路由对象,即到哪里去
- from: 当前导航正要离开的路由,即从哪里来
- next: 必须要有的,一定要调用该方法来 resolve 这个钩子。
next(), 通过当前导航,进行管道中的下一个钩子next(false),中断当前的导航next('/')或者next({ path: '/' }),当前的导航被中断,然后进行一个新的导航。next(error),传入一个Error实例,导航终止,错误信息会传递给router.onError()的回调
const router = new VueRouter({
routes: [
{
path: '/about',
meta: { auth: true },
component: () => import('../views/about.vue'),
},
]
})
// 在定义路由的时候配置了meta字段(路由元信息)
router.beforeEach((to, from, next) => {
// 路由是否需要守卫,用户是否有页面权限
if (to.meta.auth) {
// 是否登录
if (window.isLogin) {
// 如果登录了就放路由通行
next()
} else {
// 没有登录时,终止当前导航,跳转到新的页面(登录页面),同时设置了redirect:登录后应该显示的页面地址
next('/login?redirect='+to.fullPath)
}
} else {
// 无需守卫,即任何人都可以访问的页面,不需要控制页面权限的页面
next()
}
})
<template>
<div>
<button @click="login" v-if="!isLogin">登录</button>
<button @click="logout" v-else>退出</button>
</div>
</template>
<script>
export default {
methods: {
login() {
window.isLogin = true
this.$router.push(this.$route.query.redirect)
},
logout() {
window.isLogin = false
} },
computed: {
isLogin() {
return window.isLogin
}
}
}
</script>
2、beforeResolve
全局解析守卫
参数:beforeResolve(to, from, next)
使用同beforeEach(to, from, next)类似;
区别在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用
3、afterEach
全局后置钩子\
路由跳转后的钩子,不会改变导航,不需要next 参数:afterEach((to, from)
路由独享的守卫
1、beforeEnter
路由独享的守卫
可以在路由配置上直接定义 beforeEnter 守卫; 不常用
参数:beforeEnter(to, from, next)
const router = new VueRouter({
routes: [
{
path: '/about', name: 'about',
component: () => import('../views/about.vue'),
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
组件内守卫
5、beforeRouteEnter
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm => {
// 通过 `vm` 访问组件实例
})
},
6、beforeRouteUpdate
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
使用动态路径参数时,处理通过watch $route的方式监听路由还可以通过beforeRouteUpdate钩子
7、beforeRouteLeave
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
小结
- 离开组件:
beforeRouteLeave - 全局组件拦截:
beforeEach - 在路由配置里调用
beforeEnter - 进入组件内,组件激活:
beforeRouteEnter - 调用全局解析守卫:
beforeResolve - 路由跳转完后,调用全局后置守卫:
afterEach - 组件参数更新:
beforeRouteUpdate