导航的过程为了保持良好的可扩展性,设计了守卫及钩子,守卫可以重定向路由,而钩子则不能修改导航本身。守卫跟钩子有全局定义的,也有路由私有的,全局定义的每次导航都会被调用,而路由私有的则只会导航到相应路由时才会被调用。
文章目录
- 全局守卫
- 全局前置守卫
- 全局解析守卫
- 全局钩子
- 全局后置钩子
- 路由守卫
- 组件守卫
- 完整的导航解析流程
全局守卫
全局前置守卫
通过 router.beforeEach
注册一个全局前置守卫
1
2
3
4
5router.beforeEach((to, from) => { // 返回 false 以取消导航 return false })
可以注册多个全局前置守卫,当导航触发时,全局前置守卫按创建顺序依次调用。
每个守卫方法接收两个参数:
- to:目标路由
- from:来源路由
可以返回的值:
- false:取消当前导航。如果是页内导航,则导航被阻止,页面不会发生跳转,url 也不会发生变更。如果 url 发生变化(比如通过手动修改或者浏览器后退按钮),则会显示空页面。
- 无返回:继续当前导航。
- 返回一个路由地址:执行路由跳转,相当于调用一次
router.push()
,当前导航被中断,进行一个新的导航。
1
2
3
4
5
6
7
8
9
10
11
12router.beforeEach(async (to, from) => { if ( // 检查用户是否已登录 !isAuthenticated && // 避免无限重定向 to.name !== 'Login' ) { // 将用户重定向到登录页面 return { name: 'Login' } } })
可选的第三个参数 next
这个参数在 4.X
版本已经不推荐使用,但是依然支持,如果在入参中添加了该参数,则必须使用该方法进行导航,所以,不要让该参数出现在参数列表中。
全局解析守卫
通过 router.beforeResolve
注册一个全局解析守卫,该守卫与 router.beforeEach
类似,每次导航都会触发,是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。
1
2
3
4
5router.beforeResolve((to, from) => { // 返回 false 以取消导航 return false })
全局钩子
全局后置钩子
通过 router.afterEach
注册一个全局后置钩子,钩子不能修改导航本身,但对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
1
2
3
4
5router.afterEach((to, from) => { // 发送一个统计信息 sendToAnalytics(to.fullPath) })
路由守卫
通过路由配置定义 beforeEnter
守卫,只有在进入路由时才会触发,不会在 params
、query
或 hash
改变时触发。例如,从 /users/2
进入到 /users/3
或者从 /users/2#info
进入到 /users/2#projects
。
1
2
3
4
5
6
7
8
9const routes = [{ path: '/users/:id', component: () => import('@/views/UserCenter.vue'), beforeEnter: (to, from) => { // reject the navigation return false }, }]
beforeEnter
可以定义为一个函数,也可以是一个函数数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function removeQueryParams(to) { if (Object.keys(to.query).length) { return { path: to.path, query: {}, hash: to.hash } } } function removeHash(to) { if (to.hash) return { path: to.path, query: to.query, hash: '' } } const routes = [{ path: '/users/:id', component: () => import('@/views/UserCenter.vue'), beforeEnter: [removeQueryParams, removeHash], }, { path: '/about', component: () => import('@/views/About.vue'), beforeEnter: [removeQueryParams], }]
组件守卫
VUE 的页面是基于组件构建的,在组件内也可以定义路由导航守卫
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const UserDetails = { template: `...`, beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被验证前调用 // 不能获取组件实例 `this`! // 因为当守卫执行时,组件实例还没被创建! }, beforeRouteUpdate(to, from) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候, // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this` }, beforeRouteLeave(to, from) { // 在导航离开渲染该组件的对应路由时调用 // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this` } }
beforeRouteEnter
不能访问组件本身,因为该守卫是在组件创建前被调用,所以 beforeRouteEnter
提供了第三个参数 next
,在组件创建后执行回调,组件实例作为回调方法的入参。
1
2
3
4
5
6beforeRouteEnter (to, from, next) { next(vm => { // 通过 `vm` 访问组件实例 }) }
beforeRouteUpdate
或者 beforeRouteLeave
则不需要 next
参数,因为这两个守卫被执行时,组件实例都是已经存在的情况。
beforeRouteLeave
通常用来预防用户在还未保存修改前突然离开,通过返回 false 来取消。
1
2
3
4
5
6
7beforeRouteLeave (to, from) { const answer = window.confirm('页面数据尚未保存,确定要关闭吗!') if (!answer) { return false } }
如果使用组合 API 和 setup
函数来编写组件,通过 onBeforeRouteUpdate
和 onBeforeRouteLeave
来添加守卫。
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫(2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
最后
以上就是文静羊最近收集整理的关于Vite+Vue3+TS(4)整合路由组件Vue-Router之导航守卫的全部内容,更多相关Vite+Vue3+TS(4)整合路由组件Vue-Router之导航守卫内容请搜索靠谱客的其他文章。
发表评论 取消回复