Vue Router 的导航守卫
导航守卫是什么
导航守卫是 Vue Router 提供的钩子函数,在路由跳转的不同阶段执行,可以用来拦截、放行或重定向导航。可以把它们理解为路由级别的"中间件"——在进入目标页面前执行一系列检查,只有检查通过才真正完成跳转。
三种守卫类型
Vue Router 的导航守卫按作用范围分为三类:
全局守卫:挂载在 router 实例上,对所有路由生效。
js
const router = createRouter({ ... })
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 检查是否需要登录
if (to.meta.requiresAuth && !isLoggedIn()) {
next('/login')
} else {
next()
}
})
// 全局后置钩子
router.afterEach((to, from) => {
document.title = to.meta.title || '默认标题'
})路由守卫:在路由配置中定义,只对特定路由生效。
js
const routes = [
{
path: '/admin',
component: AdminPage,
beforeEnter: (to, from, next) => {
// 只有进入 /admin 时触发
next()
}
}
]组件内守卫:在组件内部定义,与组件生命周期绑定。
js
export default {
beforeRouteEnter(to, from, next) {
// 组件实例尚未创建,无法访问 this
next(vm => {
// vm 是组件实例
})
},
beforeRouteUpdate(to, from) {
// 路由参数变化但组件被复用时触发
},
beforeRouteLeave(to, from) {
// 离开当前路由前触发,常用于表单未保存的提示
const answer = window.confirm('有未保存的修改,确定离开吗?')
if (!answer) return false
}
}完整的导航解析流程
当一次路由跳转发生时,守卫的执行顺序是固定的:
beforeRouteLeave—— 离开组件内的守卫最先触发beforeEach—— 全局前置守卫beforeRouteUpdate—— 如果组件被复用(如/user/1→/user/2)beforeEnter—— 路由配置中的守卫beforeRouteEnter—— 进入组件内的守卫beforeResolve—— 全局解析守卫(Vue Router 4 新增)afterEach—— 全局后置钩子,不接受next,导航已确认
理解这个顺序对于调试权限校验逻辑很重要。如果在 beforeEach 中做了登录拦截,但组件内 beforeRouteEnter 又做了一遍检查,就需要判断是否有必要保留双重校验。
next 的变迁
Vue Router 3 中守卫必须调用 next() 来决定导航走向,不调用则会挂起。Vue Router 4 做了简化——next 不再是必选参数。如果守卫没有返回值且不调用 next,导航默认放行;返回 false 则取消导航;返回路径字符串或对象则重定向。
这种设计降低了遗漏 next() 导致路由卡死的风险,但迁移老项目时需要注意兼容性。