1. **全局前置守卫(`beforeEach`)**
- **定义位置和基本语法**:
- 在路由模块(通常是`router/index.js`)中,通过`router.beforeEach`方法来定义全局前置守卫。它接收一个回调函数,这个回调函数有三个参数:`to`(即将要进入的目标路由)、`from`(当前路由)和`next`(一个用于控制导航流程的函数)。
- **示例代码**:
```javascript
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
const router = new Router({
// 路由配置
routes: [
// 路由列表
]
});
router.beforeEach((to, from, next) => {
// 检查用户是否登录,假设登录状态存储在localStorage的'token'字段
const token = localStorage.getItem('token');
if (to.meta.requiresAuth &&!token) {
// 如果目标路由需要认证且用户未登录,重定向到登录页
next('/login');
} else {
// 否则允许导航继续
next();
}
});
export default router;
```
- **详细解释**:
- `to`对象包含了目标路由的各种信息,如路径(`to.path`)、参数(`to.params`)、查询参数(`to.query`)和路由元信息(`to.meta`)等。`from`对象同理,包含了当前路由的相关信息。
- `next`函数是控制导航流程的关键。如果不调用`next`,导航就会被中断。可以传递不同的参数给`next`:
- 不带参数调用`next()`:允许导航继续,这是最常见的情况,用于正常的路由跳转。
- 传递一个路径字符串给`next`,如`next('/some - other - route')`:将导航重定向到指定的路径。
- 传递`false`给`next`:中断当前导航。这在一些权限验证不通过等情况下很有用,比如用户没有足够的权限访问某个页面。
2. **全局解析守卫(`beforeResolve`)**
- **定义位置和基本语法**:
- 在路由模块中,通过`router.beforeResolve`来定义。它的参数和`beforeEach`一样,也是`to`、`from`和`next`。
- **示例代码**:
```javascript
router.beforeResolve((to, from, next) => {
// 假设在这里进行复杂的数据加载或权限检查
const userPermissions = getCurrentUserPermissions();
if (to.meta.requiresPermission &&!userPermissions.includes(to.meta.requiredPermission)) {
// 如果用户没有目标路由所需的权限,重定向到权限不足页面
next('/permission - denied');
} else {
// 允许导航继续
next();
}
});
```
- **详细解释**:
- `beforeResolve`在导航被确认之前,且在所有组件内守卫和异步路由组件被解析之后调用。这意味着在这个阶段,组件的`beforeRouteEnter`等守卫已经执行(如果有),可以利用这个阶段进行一些涉及多个组件或者需要组件数据加载完成后的最终检查,比如检查用户对目标路由的复杂权限是否满足。
3. **全局后置守卫(`afterEach`)**
- **定义位置和基本语法**:
- 在路由模块中,使用`router.afterEach`来定义。它接收`to`和`from`两个参数,没有`next`函数,因为此时导航已经完成。
- **示例代码**:
```javascript
router.afterEach((to, from) => {
// 根据目标路由设置页面标题
document.title = to.meta.title || '默认标题';
// 可以在这里进行页面访问统计等操作
console.log('访问了页面:', to.path);
});
```
- **详细解释**:
- 全局后置守卫主要用于在路由跳转完成后进行一些操作,比如根据不同的路由设置页面标题,方便用户在浏览器标签栏看到正确的页面标题。也可以在这里记录页面访问信息,用于分析用户行为,例如发送页面访问数据到服务器进行统计分析。
4. **路由独享守卫(`beforeEnter`)**
- **定义位置和基本语法**:
- 在路由配置对象的某个具体路由中定义。它也是接收`to`、`from`和`next`三个参数。
- **示例代码**:
```javascript
const router = new Router({
routes: [
{
path: '/admin - dashboard',
component: AdminDashboardComponent,
beforeEnter: (to, from, next) => {
// 检查用户是否是管理员,假设通过检查用户角色字段来判断
const userRole = getCurrentUserRole();
if (userRole === 'admin') {
next();
} else {
// 如果不是管理员,重定向到普通用户页面
next('/user - dashboard');
}
}
}
]
});
```
- **详细解释**:
- 路由独享守卫只对它所在的特定路由生效。这使得可以针对某个特殊的路由进行单独的权限控制或者其他操作。比如在上面的例子中,只有用户角色是`admin`才能访问`/admin - dashboard`这个路由,否则会被重定向到`/user - dashboard`。
5. **组件内守卫**
- **`beforeRouteEnter`**:
- **定义位置和基本语法**:
- 在组件内部定义,是一个组件选项。它接收`to`、`from`和`next`三个参数。
- **示例代码**:
```javascript
export default {
beforeRouteEnter(to, from, next) {
// 假设这里要根据路由参数提前获取数据
const id = to.params.id;
getDataById(id).then((data) => {
// 通过next的回调来将数据传递给组件实例
next((vm) => {
vm.someData = data;
});
});
},
data() {
return {
someData: null
};
}
};
```
- **详细解释**:
- 这个守卫在路由进入组件之前被调用。需要注意的是,此时组件实例还未创建,所以不能直接访问组件实例的属性和方法。可以通过`next`函数的回调来访问即将创建的组件实例,并将数据传递给它。在上面的例子中,先根据路由参数获取数据,然后在组件实例创建后将数据赋值给组件的`someData`属性。
- **`beforeRouteUpdate`**:
- **定义位置和基本语法**:
- 在组件内部定义,也是一个组件选项。它接收`to`、`from`和`next`三个参数。
- **示例代码**:
```javascript
export default {
beforeRouteUpdate(to, from, next) {
// 假设组件会根据路由参数更新数据
const newId = to.params.id;
updateDataById(newId).then((data) => {
this.someData = data;
next();
});
},
data() {
return {
someData: null
};
}
};
```
- **详细解释**:
- 这个守卫在当前路由改变,但是该组件被复用时调用。比如,当路由参数发生变化,组件需要根据新的参数更新数据时就很有用。在上面的例子中,当路由参数`id`发生变化时,根据新的`id`获取数据并更新组件的`someData`属性,然后调用`next()`允许导航继续。
- **`beforeRouteLeave`**:
- **定义位置和基本语法**:
- 在组件内部定义,同样是组件选项。它接收`to`、`from`和`next`三个参数。
- **示例代码**:
```javascript
export default {
beforeRouteLeave(to, from, next) {
// 假设要在离开组件前保存数据
const unsavedData = this.someData;
saveData(unsavedData).then(() => {
next();
});
},
data() {
return {
someData: null
};
}
};
```
- **详细解释**:
- 这个守卫在离开当前路由组件之前被调用。可以用于在离开组件前进行一些操作,比如保存用户在组件内编辑但尚未保存的数据。在上面的例子中,先获取组件内的数据`someData`,然后保存数据,保存完成后调用`next()`允许导航离开组件。