Vue.js全局守卫通常写在路由配置文件中,一般位于项目src/router/index.js或src/router.js(具体路径根据项目结构调整),在该文件中,通过router实例注册全局守卫,如使用router.beforeEach()定义全局前置守卫,用于导航跳转前进行权限校验、登录状态检查等逻辑;router.afterEach()则用于全局后置钩子,适合在导航完成后执行如页面滚动、日志记录等操作,全局守卫需在路由实例创建后、Vue应用挂载前配置,以确保在路由导航过程中生效。
Vue.js全局守卫配置位置与最佳实践指南
在Vue.js项目中,全局守卫(Global Guards)作为路由控制的核心机制,承担着路由跳转前后的逻辑拦截任务,如权限校验、登录状态验证、页面标题动态修改等,初学者常面临一个关键问题:全局守卫应如何正确配置? 本文将系统解答配置位置的选择,并结合实战场景提供最佳实践方案。
全局守卫的核心配置原则:路由实例注册
Vue.js的全局守卫(beforeEach、beforeResolve、afterEach)必须注册在路由实例(Router Instance)上,因此配置代码应统一写入路由配置文件,在标准Vue项目中,该文件通常位于 src/router/index.js(Vue CLI)或 src/router.js(Vite项目)。
为何必须配置在路由文件?
全局守卫的作用域覆盖整个应用,而路由实例是Vue Router的核心调度器,它管理所有路由规则,并在路由切换时触发守卫逻辑。**将守卫注册在路由实例上**,可确保所有路由跳转均经过统一拦截,避免因分散配置导致逻辑遗漏或冲突。
多场景下的路由配置定位
尽管 src/router/index.js 是通用方案,但项目创建工具(Vue CLI/Vite/Nuxt.js)可能影响文件命名,以下是典型场景:
Vue CLI项目(Vue 2/3)
默认路由配置文件 src/router/index.js 导出路由实例:
Vue.use(VueRouter)
const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/login', name: 'Login', component: Login } ]
const router = new VueRouter({ routes })
// 全局前置守卫 router.beforeEach((to, from, next) => { const isAuthenticated = localStorage.getItem('token') if (to.meta.requiresAuth && !isAuthenticated) { next('/login') // 未登录拦截 } else { next() // 正常放行 } })
// 全局后置钩子 router.afterEach((to) => { document.title = to.meta.title || '默认标题' })
export default router
<h4>Vite项目(Vue 3 + Router 4.x)</h4>
<p>使用组合式API,路由配置位于 <code>src/router/index.js</code>,API兼容Vue Router 3.x:</p>
```javascript
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
const routes = [
// 路由规则同上
]
const router = createRouter({
history: createWebHistory(),
routes
})
// 守卫注册方式与Vue 2一致
router.beforeEach((to, from, next) => {
// 权限校验逻辑
})
export default router
路由模块化场景
当路由规则按业务拆分(如 src/router/modules/user.js),**全局守卫仍需在合并路由实例后注册**:
const routes = [ { path: '/', redirect: '/user' }, ...userRoutes, ...productRoutes ]
const router = createRouter({ history: createWebHistory(), routes })
// 全局守卫必须在此注册 router.beforeEach((to, from, next) => { // 合并后的路由才能正确拦截 })
export default router
<h3>全局守卫实战场景与代码优化</h3>
<h4>1. 动态权限控制</h4>
<p>基于用户角色(admin/user/guest)精细化控制路由访问:</p>
```javascript
router.beforeEach((to, from, next) => {
const userRole = localStorage.getItem('role')
// 校验角色权限
if (to.meta.roles && !to.meta.roles.includes(userRole)) {
next('/403') // 无权限跳转
} else {
next()
}
})
登录状态深度校验
支持登录后自动跳转回目标页面,优化用户体验:
```javascript router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (to.meta.requiresAuth && !token) { next(`/login?redirect=${encodeURIComponent(to.path)}`) // 保留目标路径 } else { next() } }) ```异步权限校验(进阶)
守卫中处理异步请求(如API鉴权),需确保守卫完成后再放行:
```javascript router.beforeEach(async (to, from, next) => { if (to.meta.requiresAuth) { try { const res = await checkAuth() // 异步鉴权API if (res.valid) next() else next('/login') } catch (error) { next('/error') // 异常处理 } } else { next() } }) ```动态管理
结合路由元信息(meta)实现标题动态渲染:
```javascript router.afterEach((to) => { const title = to.meta.title ? `${to.meta.title} - Vue App` : 'Vue Application' document.title = title }) ```最佳实践与避坑指南
守卫性能优化
避免在守卫中执行耗时操作,异步逻辑需妥善处理:
```javascript // ❌ 错误示例:直接发起异步请求 router.beforeEach((to, from, next) => { fetch('/api/auth').then(() => next()) // 阻塞路由跳转 })// ✅ 正确方案:异步守卫 + Promise处理 router.beforeEach(async (to, from, next) => { if (to.meta.requiresAuth) { await checkAuthAsync() // 返回Promise的校验函数 next() } })
<h4>守卫执行顺序控制</h4>
<p>全局守卫的执行链路:<code>beforeEach → 路由组件内守卫 →