Vue.js 是一个用于构建用户界面的渐进式框架。在大型应用中,路由是管理页面间导航的关键部分。Vue Router 提供了一系列的路由守卫,帮助开发者在用户导航到新页面时执行特定逻辑。本文将详细介绍 Vue.js 中的全部路由守卫,包括如何使用、适用场景以及一些补充说明。
一、路由守卫分类
Vue Router 中的路由守卫主要分为以下几类:
-
全局守卫
-
beforeEach
-
beforeResolve
-
afterEach
-
路由独享守卫
-
组件内守卫
-
beforeRouteEnter
-
beforeRouteUpdate
-
beforeRouteLeave
二、全局守卫
全局守卫是对整个应用生效的,无论是从哪个页面到哪个页面,都会触发这些守卫。
1. beforeEach
beforeEach
是一个全局前置守卫,在每次导航发生前执行。常用于检查用户是否有权限访问某个页面。
使用方法:
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './views/Home.vue';
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{ path: '/', component: Home },
{ path: '/about', component: () => import('./views/About.vue') },
],
});
router.beforeEach((to, from, next) => {
// 例如检查用户是否登录
if (to.meta.requiresAuth && !isUserLoggedIn()) {
next('/login');
} else {
next();
}
});
export default router;
使用场景:
-
权限控制:确保用户在进入某些受限页面前已经登录。
-
全局设置:如每次导航前设置加载动画。
2. beforeResolve
beforeResolve
是全局解析守卫,它在组件内守卫和异步路由组件被解析之后才被调用。通常用于在确认导航前执行最后的异步操作。
使用方法:
router.beforeResolve((to, from, next) => {
// 例如获取动态数据
fetchData(to).then(() => {
next();
}).catch(() => {
next(false); // 取消导航
});
});
使用场景:
3. afterEach
afterEach
是全局后置守卫,在每次导航完成后执行。与 beforeEach
不同,它没有 next
参数,因为导航已经完成。
使用方法:
router.afterEach((to, from) => {
// 例如停止加载动画
stopLoading();
});
使用场景:
-
日志记录:记录每次导航的路径信息。
-
全局设置:如修改页面标题或停止全局加载动画。
三、路由独享守卫
路由独享守卫是针对单个路由生效的。
beforeEnter
beforeEnter
守卫只在进入特定路由时触发,不会在组件重用时触发。它适用于为某个特定路由添加独立的导航逻辑。
使用方法:
const router = new VueRouter({
routes: [
{
path: '/about',
component: () => import('./views/About.vue'),
beforeEnter: (to, from, next) => {
if (hasPermission(to)) {
next();
} else {
next('/login');
}
},
},
],
});
使用场景:
-
单页权限控制:为某个页面单独设置访问权限。
-
数据预处理:在进入页面前获取必要的数据。
四、组件内守卫
组件内守卫是在组件定义内部使用的,它们只对所属组件的实例生效。
1. beforeRouteEnter
beforeRouteEnter
只有在进入路由时触发。它不同于其他守卫的一个关键点是,它不能直接访问 this
,因为组件实例还未被创建。不过,可以通过回调函数在导航确认后访问组件实例。
使用方法:
export default {
beforeRouteEnter(to, from, next) {
next((vm) => {
// 组件实例已经创建
vm.fetchData();
});
},
methods: {
fetchData() {
// 获取数据逻辑
},
},
};
使用场景:
-
数据预处理:在组件渲染前预处理数据,并在导航完成后初始化数据。
2. beforeRouteUpdate
beforeRouteUpdate
在当前路由改变,但是依然渲染同一个组件时触发。适用于当一个动态参数变化时,需要重新获取数据的场景。
使用方法:
export default {
beforeRouteUpdate(to, from, next) {
this.fetchData();
next();
},
methods: {
fetchData() {
// 根据新参数获取数据
},
},
};
使用场景:
-
动态数据更新:响应路由参数的变化,重新获取或更新数据。
3. beforeRouteLeave
beforeRouteLeave
在导航离开组件对应的路由时调用。常用于确认用户是否保存了当前表单内容。
使用方法:
export default {
beforeRouteLeave(to, from, next) {
if (this.hasUnsavedChanges) {
const answer = window.confirm('You have unsaved changes. Do you really want to leave?');
if (answer) {
next();
} else {
next(false);
}
} else {
next();
}
},
data() {
return {
hasUnsavedChanges: false,
};
},
};
使用场景:
-
表单验证:阻止用户在表单未保存时意外离开页面。
-
清理工作:在离开页面前执行清理或重置工作。
五、补充说明
-
导航流程:Vue Router 的导航流程遵循以下顺序:
-
触发 beforeEach
全局前置守卫。
-
在路由配置中触发 beforeEnter
守卫。
-
解析异步路由组件。
-
触发 beforeRouteEnter
组件内守卫。
-
触发 beforeResolve
全局解析守卫。
-
完成导航。
-
触发 afterEach
全局后置守卫。
-
next
函数的使用:next
函数控制导航的流程,可以接受以下参数:
-
next()
:继续当前导航。
-
next(false)
:中断当前导航。
-
next('/')
或 next({ path: '/' })
:导航到一个不同的路径。
-
异步操作:在守卫中执行异步操作时,需要确保异步操作完成后调用 next
,否则导航将被卡住。
六、总结
Vue.js 的路由守卫为我们提供了强大的工具来管理应用中的导航逻辑。通过灵活使用全局守卫、路由独享守卫和组件内守卫,我们可以轻松实现权限控制、数据预处理和用户交互保护等功能。希望通过这篇文章,你能够更好地理解并应用这些守卫,构建更健壮的 Vue.js 应用。