导航守卫
正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
全局前置守卫
你可以使用
router.beforeEach
注册一个全局前置守卫:
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中 。
每个守卫方法接收两个参数:
可以返回的值如下:
-
false
: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。 -
一个
路由地址
: 通过一个路由地址跳转到一个不同的地址,就像你调用
router.push()
一样,你可以设置诸如replace: true
或name: 'home'
之类的配置。当前的导航被中断,然后进行一个新的导航,就和from
一样。
如果遇到了意料之外的情况,可能会抛出一个
Error
。这会取消导航并且调用
router.onError()
注册过的回调。
如果什么都没有,
undefined
或返回
true
,
则导航是有效的
,并调用下一个导航守卫
以上所有都同
async
函数
和 Promise 工作方式一样:
可选的第三个参数
next
在之前的 Vue Router 版本中,也是可以使用
第三个参数
next
的。这是一个常见的错误来源,可以通过
RFC
来消除错误。然而,它仍然是被支持的,这意味着你可以向任何导航守卫传递第三个参数。在这种情况下,
确保
next
在任何给定的导航守卫中都被
严格调用一次
。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。这里有一个在用户未能验证身份时重定向到
/login
的
错误用例
:
下面是正确的版本:
全局解析守卫
你可以用
router.beforeResolve
注册一个全局守卫。这和
router.beforeEach
类似,因为它在
每次导航
时都会触发,不同的是,解析守卫刚好会在导航被确认之前、
所有组件内守卫和异步路由组件被解析之后
调用。这里有一个例子,确保用户可以访问
自定义 meta
属性
requiresCamera
的路由:
router.beforeResolve
是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受
next
函数也不会改变导航本身:
它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
它们也反映了 navigation failures 作为第三个参数:
了解更多关于 navigation failures 的信息在 它的指南 中。
路由独享的守卫
你可以直接在路由配置上定义
beforeEnter
守卫:
beforeEnter
守卫
只在进入路由时触发
,不会在
params
、
query
或
hash
改变时触发。例如,从
/users/2
进入到
/users/3
或者从
/users/2#info
进入到
/users/2#projects
。它们只有在
从一个不同的
路由导航时,才会被触发。
你也可以将一个函数数组传递给
beforeEnter
,这在为不同的路由重用守卫时很有用:
请注意,你也可以通过使用 路径 meta 字段 和 全局导航守卫 来实现类似的行为。
组件内的守卫
最后,你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)
可用的配置 API
你可以为路由组件添加以下配置:
-
beforeRouteEnter
-
beforeRouteUpdate
-
beforeRouteLeave
beforeRouteEnter
守卫
不能
访问
this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给
next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数:
注意
beforeRouteEnter
是支持给
next
传递回调的唯一守卫。对于
beforeRouteUpdate
和
beforeRouteLeave
来说,
this
已经可用了,所以
不支持
传递回调,因为没有必要了:
这个
离开守卫
通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回
false
来取消。