一文详解vue-router中的导航守卫
作者:舟羽
导航守卫是什么
按照官方文档说明,vue-router
提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
在 vue-router
中,导航守卫是一种非常重要的功能,它允许你在路由导航过程中添加逻辑验证和处理,比如判断用户是否登录,如果没有登录就跳转到登录页面,如果已经登录就跳转到首页。
导航守卫的分类
在 Vue Router
中,有三种类型的导航守卫方法可以使用:
全局守卫:
beforeEach
和afterEach
。独享路由守卫:
beforeEnter
。组件内路由守卫:
beforeRouteEnter
、beforeRouteUpdate
和beforeRouteLeave
。
全局守卫
全局守卫就是在路由跳转时,对整个应用内的所有路由进行拦截,然后进行一些操作。
全局守卫分为全局前置守卫
和全局后置守卫
。
全局前置守卫
就是在路由跳转之前进行拦截,全局后置守卫
就是在路由跳转之后进行拦截。
全局前置守卫的使用方法如下:
router.beforeEach((to, from, next) => { // ... })
全局后置守卫的使用方法如下:
router.afterEach((to, from) => { // ... })
路由独享守卫
路由独享守卫就是在路由跳转时,对应用内的某个特定的路由进行拦截,然后进行一些操作。
路由独享守卫的使用方法如下:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
组件内守卫
组件内守卫就是在组件内部定义的特殊守卫方法,用于处理组件级别的路由导航。常见的组件内守卫包括:
beforeRouteEnter
: 在路由进入组件之前被调用,可以访问不到组件实例(this),但可以通过回调函数获取组件实例。beforeRouteUpdate
: 在当前路由被复用时调用,例如同一个组件在不同参数下进行切换时。beforeRouteLeave
: 在离开当前路由之前调用,可以询问用户是否保存未保存的数据或执行其他清理操作。
const UserDetails = { template: `...`, beforeRouteEnter(to, from) { // 在渲染该组件的对应路由被验证前调用 // 不能获取组件实例 `this` ! // 因为当守卫执行时,组件实例还没被创建! }, beforeRouteUpdate(to, from) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候, // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this` }, beforeRouteLeave(to, from) { // 在导航离开渲染该组件的对应路由时调用 // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this` }, }
导航守卫的参数
导航守卫的参数如下:
to
: 即将要进入的目标路由对象,包含了目标路由的路径、参数、查询参数等信息,可以用来判断要导航到哪个路由。from
: 当前导航正要离开的路由,包含了当前路由的路径、参数、查询参数等信息,可以用来判断当前路由的状态。next
方法:用于控制导航行为。它有以下几种用法:next()
: 允许导航,继续进行下一步导航操作。next(false)
: 取消导航,终止当前导航操作。next('/')
或next({ path: '/' })
: 重定向到指定的路径。next(error)
: 导航出错,可以传递一个错误对象给 next 方法。
导航守卫的执行顺序
导航守卫的执行顺序如下:
全局前置守卫 -> 路由独享守卫 -> 组件内守卫 -> 全局后置守卫
导航守卫的使用场景
全局前置守卫
- 判断用户是否登录,如果没有登录就跳转到登录页面,如果已经登录就跳转到首页。
router.beforeEach((to, from, next) => { if (to.path === '/login') { next() } else { const token = localStorage.getItem('token') if (!token) { next('/login') } else { next() } } })
全局后置守卫
- 记录用户访问的页面。
router.afterEach((to, from) => { localStorage.setItem('path', to.path) })
路由独享守卫
- 判断用户是否有权限访问某个页面,如果没有权限就跳转到首页。
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { const token = localStorage.getItem('token') if (!token) { next('/') } else { const role = localStorage.getItem('role') if (to.meta.role && to.meta.role.indexOf(role) === -1) { next('/') } else { next() } } } } ] })
组件内守卫
- 数据预加载:在进入组件之前,需要先加载一些数据。可以使用
beforeRouteEnter
组件内守卫来调用接口获取数据,并在数据加载完成后再进入组件。
const Foo = { beforeRouteEnter(to, from, next) { fetchData().then(data => { next(vm => { vm.data = data; // 将数据传递给组件实例 }); }); }, };
- 路由参数更新:当同一个组件在不同参数下进行切换时,可能需要根据新的参数更新组件的数据或状态。可以使用
beforeRouteUpdate
组件内守卫来处理这种情况。
const Baz = { beforeRouteUpdate(to, from, next) { if (to.params.id !== from.params.id) { // 当路由参数 id 发生变化时,重新请求数据 this.fetchData(to.params.id); } next(); }, };
- 数据清理:在离开当前路由之前需要执行一些清理操作,例如取消订阅事件、重置组件状态等。可以使用
beforeRouteLeave
组件内守卫来处理这些操作。
const Bar = { beforeRouteLeave(to, from, next) { if (this.hasUnsavedChanges()) { if (confirm('是否保存修改的数据?')) { this.saveData(); // 保存修改的数据 } } next(); };
- 页面切换动画:在切换页面时添加过渡动画效果,以提升用户体验。可以在
beforeRouteEnter
和beforeRouteLeave
组件内守卫中设置过渡动画的相关逻辑。
const Qux = { beforeRouteEnter(to, from, next) { // 在进入组件之前设置初始过渡状态 this.transitionName = 'slide-in'; next(); }, beforeRouteLeave(to, from, next) { // 在离开组件之前设置过渡状态 this.transitionName = 'slide-out'; next(); }, };
到此这篇关于一文详解vue-router中的导航守卫的文章就介绍到这了,更多相关vue-router导航守卫内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!