在 Vue3 项目中,通常需要对路由进行权限控制,但某些页面(如登录页、注册页、404页面等)不需要进行 Token 鉴权。以下是实现这一功能的几种方法:
方法一:使用路由元信息(meta)
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
meta: {
requiresAuth: false // 不需要鉴权
}
},
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue'),
meta: {
requiresAuth: true // 需要鉴权
}
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
// 全局前置守卫
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
// 如果路由需要鉴权且没有token,跳转到登录页
if (to.meta.requiresAuth && !token) {
next('/login')
}
// 如果已经登录又访问登录页,跳转到首页
else if (to.name === 'Login' && token) {
next('/')
}
// 其他情况正常放行
else {
next()
}
})
export default router
方法二:白名单模式
// router/index.js
// 定义不需要鉴权的路由名称白名单
const whiteList = ['Login', 'Register', 'NotFound']
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
// 如果在白名单中,直接放行
if (whiteList.includes(to.name)) {
next()
return
}
// 不在白名单且没有token,跳转到登录页
if (!token) {
next('/login')
}
// 有token正常放行
else {
next()
}
})
方法三:反向逻辑(默认需要鉴权)
// 在路由meta中明确标记不需要鉴权的路由
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
meta: {
noAuth: true // 明确标记不需要鉴权
}
}
]
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
// 如果路由不要求免鉴权且没有token,跳转到登录页
if (!to.meta.noAuth && !token) {
next('/login')
}
// 免鉴权路由或已登录用户正常放行
else {
next()
}
})
方法四:动态路由 + 鉴权分离
对于更复杂的场景,可以将路由分为常驻路由和动态路由:
// 常驻路由(不需要鉴权)
const constantRoutes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue')
}
]
// 需要鉴权的动态路由
const asyncRoutes = [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes
})
// 登录后添加动态路由
export function addRoutes() {
asyncRoutes.forEach(route => {
router.addRoute(route)
})
}
// 全局前置守卫
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
// 检查路由是否存在
if (!router.hasRoute(to.name)) {
if (token) {
addRoutes()
next(to.fullPath) // 重定向到原路径
} else {
next('/login')
}
} else {
next()
}
})
最佳实践建议
- 统一鉴权逻辑:选择一种方式并在整个项目中保持一致
- 路由懒加载:使用动态导入(
() => import()
)优化性能 - 错误处理:添加404页面处理未匹配路由
- Token存储:考虑使用更安全的存储方式如httpOnly cookie
- 路由元信息扩展:可以扩展meta对象包含更多权限信息,如角色权限等
meta: {
requiresAuth: true,
roles: ['admin', 'editor']
}
通过以上方法,你可以灵活地控制哪些路由需要鉴权,哪些路由可以直接访问。