第一步
区分路由表
需要到动态路由的场景一般都是在切换身份权限,所以我们需要将功能路由页面与权限页面区分开来,那么我们就会得到两个路由表
export const routes = [
{
//调试环境
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'login',
component: () => import('@/views/login.vue'),
},
{
path: '/error',
name: 'error',
component: () => import('@/views/error/error.vue'),
}, {
path: '/main',
name: 'main',
redirect: '/main/dashboard',
component: () => import('@/views/main.vue'),
meta: {
roles: ['0']
},
children: [
{
path: 'dashboard',
name: 'dashboard',
component: () => import('@/views/dashboard/dashboard.vue'),
}
]
}
]
export const RoleRoutes = [
{
path: 'order',
name: 'order',
component: () => import('@/views/order/order.vue'),
meta: {
roles: ['0']
}
},
{
path: 'user',
name: 'user',
component: () => import('@/views/user/user.vue'),
meta: {
roles: ['0']
}
}, {
path: 'product',
name: 'product',
component: () => import('@/views/product/product.vue'),
meta: {
roles: ['0']
}
}
]
第一个路由表是公共路由表,不涉及到身份权限判断,第二个路由表我们根据meta配置roles来判断该路由所需要的身份权限
第二步
使用Pinia保存当前用户的身份
state: () => {
return {
role:localStorage.getItem('role') ? localStorage.getItem('role') : null,
}
},
在我们用户登录时,我们需要将用户的身份存入Pinia中
第三步
在全局路由守卫中对用户身份进行判断,并动态添加路由
判断访问页面所需权限
我们使用filterAsyncRoutes方法将RoleRoutes路由表作为第一个参数传入,将当前的用户身份roles作为第二个参数传入,用forEach循环以及解构赋值并使用hasPermission函数判断哪些页面的权限符合当前用户的身份,将符合条件的页面push到res数组中。
filterAsyncRoutes函数:
/**
* Filter asynchronous routing tables by recursion
* @param routes asyncRoutes
* @param roles
*/
export function filterAsyncRoutes(routes: any, roles: any) {
const res:any = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(roles, tmp)) {
res.push(tmp)
}
})
return res
}
hasPermission函数:
function hasPermission(role: string, route: any) {
if (route.meta && route.meta.roles) {
return route.meta.roles.includes(role)
} else {
return true
}
}
动态添加路由
为了应付用户刷新,路由失效的问题,我们需要定义一个自定义标识registerRouteFresh,初始化为true,在首次加载时,让页面路由动态添加至路由表中,在下次跳转路由后不执行addRoute;在用户刷新页面时,registerRouteFresh被初始化为true,重新进行路由动态加载,路由动态加载完成后registerRouteFresh置为false不再重复添加
let registerRouteFresh = true // 定义标识,记录路由是否添加
router.beforeEach((to, from, next) => {
const userStore = useUserStore()
const roleStore = useRoleStore()
// 判断有没有登录
if (!userStore.token) {
//如果没登录,但是去得页面是login页
if (to.name == "login") {
next();
} else {
message.error('请先完成登录!')
router.push('/login')
}
} else {
//如果登录了
//首次登录跳转动态添加路由状态是true
if (registerRouteFresh) {
if (!userStore.role) {
userStore.GET_ROLE()
}
const role = userStore.role || localStorage.getItem('role')
const addRouter = filterAsyncRoutes(RoleRoutes, role)
addRouter.forEach((v: any) => {
router.addRoute('main', v)
})
next({ ...to, replace: true })
registerRouteFresh = false
} else {
next()
}
}
});
结束
最近一段时间学习完Vue3将毕设的后台独立分离出来使用Vue3+Vite+Pinia+TypeScript重构了一下,这篇文章作为一个记录,下一篇文章应该就是用React将这个项目再次重构了