Vue 教程(四十五)Vue 导航守卫
Posted _否极泰来_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 教程(四十五)Vue 导航守卫相关的知识,希望对你有一定的参考价值。
Vue 教程(四十五)Vue 导航守卫
什么是导航守卫
“导航”表示路由正在发生变化
导航守卫表示当导航开始变化到导航变化结束的那段时间里,根据导航的变化做出一些响应。比如要跳转到一个页面时,看他是不是登录了,没登录的话,得让他先登录。主要是通过跳转到某处或者取消跳转来守卫导航。
Vue Router 提供的导航
Vue Router 提供的导航守卫主要用来监听监听路由的进入和离开的。
Vue Router 提供了 beforeEach 和 afterEach 的钩子函数,它们会在路由即将改变前和改变后触发。
-
修改标题需求
在一个 SPA 应用中,点击不同按钮、切换页面时,修改跳转页面对应的标题,可以通过 javascript 来修改
<title>
的内容。如果页面比较多时,在每一个路由对应的组件 .vue 文件中,通过 created 声明周期函数, 执行对应的代码进行修改,这种方式维护成本太高,下面通过导航守卫的方式实现
添加元属性
// 2. 定义路由
const routes = [
// 配置默认路径
path: '/',
redirect: '/home',
,
meta: title: '首页' ,
path: '/home',
component: () => import('../components/Home'),
children: [
meta: title: '新闻' ,
path: 'news',
component: () => import('../components/News'),
,
],
,
meta: title: '关于' ,
path: '/about',
component: () => import('../components/About'),
,
meta: title: '分类' ,
path: '/category/:categoryId',
component: () => import('../components/Category'),
,
meta: title: '用户' ,
path: '/user',
component: () => import('../components/User'),
,
]
全局守卫
-
全局前置守卫
可以使用 router.beforeEach 注册一个全局前置守卫:
// 前置钩子(guard) router.beforeEach((to, from, next) => // 设置当前标题为:要跳转页面匹配的第一个路径meta元素的标题 window.document.title = to.matched[0].meta.title // next函数:调用该方法后,才能进入下一步 next() )
每个守卫方法接收三个参数:
to : Route:即将要进入的路由对象。
from : Route:当前导航正要离开的路由对象。
next: Function:一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next() :进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false) :中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(’/’) 或者 next( path: ‘/’ ):跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace : true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
next(error):(2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。
-
全局后置守卫
可以使用 afterEach 注册全局后置钩子 ,但不需要主动调用 next() 函数。
记录用户操作日志:
// 全局后置守卫(hook)
router.afterEach((to, from) =>
console.log('操作历史:', from.meta.title + '===>' + to.meta.title)
)
路由独享的守卫
你可以在路由配置上直接定义 beforeEnter 守卫,只有当进入这个路由时才会调用的,这些守卫与全局前置守卫的方法参数是一样的。
const routes = [
// 配置默认路径
path: '/',
redirect: '/home',
,
meta: title: '首页' ,
path: '/home',
component: () => import('../components/Home'),
children: [
meta: title: '新闻' ,
path: 'news',
component: () => import('../components/News'),
,
],
,
meta: title: '关于' ,
path: '/about',
component: () => import('../components/About'),
beforeEach: (to, from, next) =>
// ...
,
,
meta: title: '分类' ,
path: '/category/:categoryId',
component: () => import('../components/Category'),
,
meta: title: '用户' ,
path: '/user',
component: () => import('../components/User'),
,
]
组件内的守卫
你可以在路由组件内直接定义以下路由导航守卫:
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
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`
,
这三个守卫是写在组件里,beforeRouteEnter 守卫不能访问 this,因为守卫在导航确认前被调用,因此即将进入的新组件还没被创建。
不过,你可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。其他两个都可以用 this。
beforeRouteEnter (to, from, next)
next(vm =>
// 通过 `vm` 访问组件实例
)
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
beforeRouteLeave (to, from, next)
const answer = window.confirm('有未保存的更改,你真的想离开吗?')
if (answer)
next()
else
next(false)
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
– 以上为《Vue 教程(四十五)Vue 导航守卫》,如有不当之处请指出,我后续逐步完善更正,大家共同提高。谢谢大家对我的关注。
——厚积薄发(yuanxw)
以上是关于Vue 教程(四十五)Vue 导航守卫的主要内容,如果未能解决你的问题,请参考以下文章