一.什么是前端路由守卫
前端路由守卫是一种在路由导航过程中进行控制的机制,允许开发者在路由切换的不同阶段执行特定的逻辑。在 Vue.js 中,路由守卫是通过 Vue Router 提供的钩子函数实现的。这些钩子函数可以用于权限验证、数据预取、错误处理等场景,从而实现高级的导航控制。
二.路由守卫的类型
Vue Router 提供了以下几种路由守卫钩子:全局前置守卫 (beforeEach):在路由跳转前执行,常用于权限验证。
全局解析守卫 (beforeResolve):在导航被确认之前执行,适用于需要等待异步操作完成的场景。
全局后置钩子 (afterEach):在路由跳转完成后执行,通常用于日志记录或页面分析。
路由独享的守卫 (beforeEnter):在特定路由配置中定义,仅对该路由生效。
组件内的守卫:
beforeRouteEnter:在进入组件前执行。
beforeRouteUpdate:在当前路由改变但组件复用时执行。
beforeRouteLeave:在离开当前路由前执行。
三.路由守卫的使用
全局前置守卫 (beforeEach)
beforeEach 是最常用的路由守卫,通常用于权限验证。import Vue from 'vue'; import VueRouter from 'vue-router';
import Home from './views/Home.vue';
import Dashboard from './views/Dashboard.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/', name:
'Home',
component: Home
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
meta: { requiresAuth: true } // 标记该路由需要身份验证
} ];
const router = new VueRouter({
routes
});
// 全局前置守卫
router.beforeEach((to, from, next) => {
// to: 即将要进入的目标路由对象
// from: 当前导航正要离开的路由对象
// next: 用于控制路由的跳转
if (to.meta.requiresAuth) {
// 模拟检查用户是否已登录
const isAuthenticated = localStorage.getItem('token');
if (!isAuthenticated) {
// 用户未登录,重定向到登录页面
next({ name: 'Home' });
} else {
next(); // 允许访问
} } else { next(); // 不需要身份验证,直接放行
}
});
export default router;
to
:目标路由对象。
from
:当前路由对象。
next
:回调函数,用于控制导航行为。在上述代码中,
beforeEach
守卫会检查目标路由是否需要身份验证(通过meta
字段标记),如果需要且用户未登录,则重定向到首页。全局解析守卫 (
beforeResolve
)
beforeResolve
全局解析守卫在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用。它可以用于在路由确认前进行最后的数据预取或验证。router.beforeResolve((to, from, next) => {
// 模拟数据预取
if (to.name === 'Dashboard') {
// 这里可以进行异步数据请求
setTimeout(() => {
console.log('数据预取完成');
next();
}, 1000);
} else {
next();
}
});
在这个例子中,当要进入
Dashboard
路由时,会模拟一个数据预取的异步操作,完成后再放行路由。全局后置钩子(
afterEach
)
afterEach
是全局后置钩子,它会在每次路由切换完成后被调用。通常用于日志记录、页面滚动处理等操作。router.afterEach((to, from) => {
// 记录路由切换日志
console.log(`从 ${from.name} 路由切换到 ${to.name} 路由`);
// 页面滚动到顶部
window.scrollTo(0, 0);
});
这里在每次路由切换完成后,会记录路由切换信息并将页面滚动到顶部。
路由独享的守卫 (
beforeEnter
)
beforeEnter
可以在特定路由配置中定义,仅对该路由生效。const routes = [
{
path: '/admin',
component: Admin,
beforeEnter: (to, from, next) => {
if (checkAdminAccess()) {
next();
} else {
next('/unauthorized');
}
}
}
];组件内的守卫
组件内的守卫可以直接在组件中定义。beforeRouteEnter:
beforeRouteEnter(to, from, next) {
next(vm => {
// 访问组件实例 `vm`
});
}
beforeRouteUpdate:beforeRouteUpdate(to, from, next) {
// 路由参数变化但组件复用时调用
next();
}
beforeRouteLeave:beforeRouteLeave(to, from, next) {
if (confirm('确定离开吗?')) {
next();
} else {
next(false); // 取消导航
}
}
四.应用场景
权限验证
在 beforeEach 中检查用户是否具有访问权限。router.beforeEach((to, from, next) => {
const isAuthenticated = checkAuth();
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login');
} else {
next();
}
});
数据预取
在 beforeRouteEnter 或 beforeResolve 中预取数据。beforeRouteEnter(to, from, next) {
fetchData().then(data => {
next(vm => vm.setData(data));
});
}
错误处理
在 beforeResolve 中处理异步操作错误。router.beforeResolve((to, from, next) => {
fetchData().then(() => next()).catch(() => next('/error'));
});
页面访问日志
在 afterEach 中记录页面访问。router.afterEach((to, from) => {
logPageView(to.path);
});
五.总结
前端路由守卫是 Vue Router 提供的强大功能,能够帮助开发者在路由导航的不同阶段执行特定的逻辑。通过合理使用 beforeEach、afterEach、beforeResolve 等钩子,可以实现权限验证、数据预取、错误处理等高级导航控制,从而提升应用的安全性和用户体验。