Test ## 导读大纲 最近在项目中使用 Vue Router 做权限控制,踩了不少坑,总结一下路由守卫的使…

Test

导读大纲

最近在项目中使用 Vue Router 做权限控制,踩了不少坑,总结一下路由守卫的使用经验:

  1. 路由守卫分类 - 路由守卫的三种类型
  2. 全局路由守卫 - 如何设置全局路由守卫
  3. 单个路由独享守卫 - 路由级别的守卫
  4. 组件路由守卫 - 组件内的路由守卫
  5. 路由守卫执行的完整过程 - 路由守卫的执行顺序

路由守卫分类

Vue Router 提供了三种类型的路由守卫:

  1. 全局路由守卫 - 作用于所有路由
  2. 单个路由独享守卫 - 作用于特定路由
  3. 组件路由守卫 - 作用于特定组件

全局路由守卫

全局路由守卫是在路由实例上直接定义的守卫函数,会在路由跳转时被调用。Vue Router 提供了三种全局守卫:

一、beforeEach

beforeEach 在路由跳转之前执行,最常用的场景就是做权限验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 全局验证路由
const router = createRouter({
history: createWebHashHistory(),
routes
});

// 白名单,不需要验证的路由
const whiteList = ['/', '/register', '/login'];

router.beforeEach((to, from, next) => {
// 判断是否在白名单中
if (whiteList.indexOf(to.path) !== -1) {
// 放行,进入下一个路由
next();
} else if (!sessionStorage.getItem('token')) {
// 没有token,跳转到登录页
next('/login');
} else {
// 有token,放行
}
});

1
参数说明:
  • to: 即将要进入的目标路由对象
  • from: 当前导航正要离开的路由对象
  • next: 调用该方法来 resolve 这个钩子
1
2
3
4
5
next() 的用法:
- `next()`: 进行管道中的下一个钩子
- `next(false)`: 中断当前的导航
- `next('/')` 或 `next({ path: '/' })`: 跳转到一个不同的地址
- `next(error)`: 如果传入的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 `router.onError()` 注册过的回调

二、beforeResolve

beforeResolve 在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用。

1
2
3
4
5
6
7
router.beforeResolve((to, from, next) => {
// 在导航被确认之前执行
// 此时组件已经解析完成
if (to.meta.requiresAuth) {
// 检查用户权限
if (checkUserPermission()) {
next('/unauthorized');
}

}

1
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

### 三、afterEach

`afterEach` 在路由跳转完成后执行,此时已经进入了目标路由,无法改变导航。

router.afterEach((to, from) => {
// 路由跳转完成后执行
// 可以用于页面访问统计、设置页面标题等
document.title = to.meta.title || '默认标题';

// 页面访问统计
if (window.gtag) {
window.gtag('config', 'GA_MEASUREMENT_ID', {
page_path: to.path
});
});

单个路由独享守卫

单个路由独享守卫是在路由配置中直接定义的 beforeEnter 守卫,只作用于该路由。

四、beforeEnter

1
const routes = [

{

1
2
3
4
5
path: '/superior',
component: Superior,
meta: {
icon: 'el-icon-s-check',
title: '上级文件'
},
1
2
3
4
beforeEnter: (to, from, next) => {
// 路由级别的守卫
// 检查用户是否有权限访问该路由
if (hasPermission('superior')) {
  }

];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

使用场景:
- 特定路由需要特殊权限验证
- 路由级别的数据预加载
- 路由参数验证

## 组件路由守卫

组件路由守卫是在组件内部定义的路由守卫,它们可以直接访问组件实例。

### 五、beforeRouteEnter

在进入该组件对应的路由前调用,此时组件实例还未创建,无法访问 `this`。

export default {
name: 'UserProfile',
beforeRouteEnter(to, from, next) {
// 组件实例还未创建
// 可以通过 next 回调访问组件实例
next(vm => {
// 通过 vm 访问组件实例
vm.loadUserData(to.params.id);
});
};

六、beforeRouteUpdate

在当前路由改变,但是该组件被复用时调用。例如,对于带有动态参数的路径 /user/:id,在 /user/1/user/2 之间跳转时,组件会被复用。

1
2
3
4
5
beforeRouteUpdate(to, from, next) {
// 可以访问组件实例 this
// 当路由参数变化时,重新加载数据
if (to.params.id !== from.params.id) {
this.loadUserData(to.params.id);
}

}
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

### 七、beforeRouteLeave

在离开该组件对应的路由前调用,常用于防止用户在未保存的情况下离开页面。

name: 'EditForm',
data() {
return {
hasUnsavedChanges: false
};
},
beforeRouteLeave(to, from, next) {
// 检查是否有未保存的更改
if (this.hasUnsavedChanges) {
const answer = window.confirm('您有未保存的更改,确定要离开吗?');
if (answer) {
next(false);
}
}
};

路由守卫执行的完整过程

路由守卫的执行顺序如下:

  1. 导航被触发
  2. 在失活的组件里调用 beforeRouteLeave 守卫
  3. 调用全局的 beforeEach 守卫
  4. 在重用的组件里调用 beforeRouteUpdate 守卫
  5. 在路由配置里调用 beforeEnter 守卫
  6. 解析异步路由组件
  7. 在被激活的组件里调用 beforeRouteEnter 守卫
  8. 调用全局的 beforeResolve 守卫
  9. 导航被确认
  10. 调用全局的 afterEach 钩子
  11. 触发 DOM 更新
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入
1
执行流程图:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
导航触发
beforeRouteLeave (组件内)
beforeEach (全局)
beforeRouteUpdate (组件内,如果组件被复用)
beforeEnter (路由配置)
解析异步路由组件
beforeRouteEnter (组件内)
beforeResolve (全局)
导航确认
afterEach (全局)
DOM 更新
beforeRouteEnter 的 next 回调
`完整示例:```javascript
// router/index.js
routes: [
{
path: '/user/:id',
component: UserProfile,
console.log('路由配置守卫');
}
]
});

// 全局守卫
console.log('全局 beforeEach');
});

console.log('全局 beforeResolve');
});

console.log('全局 afterEach');
});

// 组件内守卫
console.log('组件 beforeRouteEnter');
console.log('组件 beforeRouteEnter 回调');
});
},
console.log('组件 beforeRouteUpdate');
},
console.log('组件 beforeRouteLeave');
}
};

总结

路由守卫是Vue Router中非常重要的功能,它们可以帮助我们:

  1. 权限控制 - 根据用户权限决定是否可以访问某个路由
  2. 数据预加载 - 在进入路由前加载必要的数据
  3. 页面保护 - 防止用户在未保存的情况下离开页面
  4. 访问统计 - 记录页面访问情况
  5. 页面标题设置 - 根据路由动态设置页面标题

合理使用路由守卫可以让我们的应用更加安全和用户友好。

本文标题: Vue路由守卫安全

发布时间: 2019年05月26日 00:00

最后更新: 2025年12月30日 08:54

原始链接: https://haoxiang.eu.org/4423cba0/

版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码