vue3+pinia+路由守卫实现用户访问页面权限
每个用户能访问的路由在登陆接口返回,格式包含一个Key(用于比对数据)
如下:
[{name:'',Key:''},{name:'',Key:''}...]
在router中定义两个数组一个为需要权限才能访问的权限路由,一个为不需要权限就能访问的固定路由
//不需要权限
export const constantRoutes: RouteRecordRaw[] = [
//路由重定向
{
path: '/',
redirect: '/Layout'
},
{
path: '/login',
name: 'login',
component: login,
}]]
//需要权限
export const asyncRoutes: RouteRecordRaw[] = [ {
path: '/EventManagement',
name: '活动管理',
component: () => import('@/views/EventManagement/EventManagement.vue'),
meta: {
title: '活动管理',
authkey: 'LIFE_EVENTMANAGEMENT',
icon: 'home'
}
}]
在路由守卫中判断用户是否登录,是否添加路由,是否处理路由。
import router from '@/router/router'
import { useUserStore } from '@/store';
import { asyncRoutes } from '@/router/router'
let iscomparison = false;//判断是否添加路由
router.beforeEach((to, from, next) => {
console.log('进入路由守卫')
var userStore = useUserStore();
if (to.path === '/login') {
next()
} else {
//如果有用户名证明已经登陆,如果没有就是还没有登陆
if (userStore.name) {
//判断是否处理过账户的权限路由userStore.iscomparison为true是为处理过当登出与登录失效时,会重新变为false
if (userStore.iscomparison) {
//判断是否添加过路由(刷新的时候addRoute方法添加的路由会丢失需要重新addRoute)
if (iscomparison) {
next()
} else {
//重新添加
userStore.comparisonKeys(userStore.message.AuthList).then((res: any) => {
userStore.userProfile.addRoute.forEach(item => {
router.addRoute('Layout', item)
})
userStore.iscomparison = true;
iscomparison = true;
next({ ...to, replace: true })
})
}
} else {
//如果没有处理过权限路由,判断有没有添加过路由
if (iscomparison) {
//添加过路由(在退出登陆与登陆超时会遇到)首先将之前添加的路由删除再将iscomparison设置为false再跑一次路由守卫
//userStore.userProfile.addRoute.forEach(item => {
// router.removeRoute(item.name)
//})
iscomparison = false;
next({ ...to, replace: true })
} else {
//没有添加过路由也没有处理过权限,处理权限
userStore.comparisonKeys(userStore.message.AuthList).then((res: any) => {
userStore.userProfile.addRoute.forEach(item => {
router.addRoute('Layout',item)
})
userStore.iscomparison = true;
iscomparison = true;
next({ ...to, replace: true })
})
}
}
} else {
next('/login')
}
}
})
先说说这一次踩的坑:
1.登录之后一直白屏,在路由守卫中console.log(‘进入路由守卫’)发现一直进入路由守卫问了神奇的度娘之后才知道,next({ …to, replace: true })、next(‘/login’)与next()的区别。在路由守卫中next({ …to, replace: true })和next(‘/login’)会再次进入路由守卫而next()为放行不会再次进入路由守卫。
2.登录之后跳转到后台管理页面,看起来一点问题都没有了,但是刷新页面之后,之前使用router.addRouter()方法添加的权限路由不见了!!!!原因是刷新页面的时候路由也会跟着一起初始化,后面添加权限路由也会随之消失,解决方法是在router.ts中声明一个变量let iscomparison = false;
当iscomparison 为false时代表还没有使用router.addRouter()添加权限路由反之为已经添加了路由防止重复添加,再刷新页面的时候iscomparison 也会随着路由一起初始化。
3.切换账号时,上一个账号的路由权限没有删除,比如我先登陆一个叫admin的管理员账号,登出后再登陆一个叫test的用户账号,会发现在test账号中可以访问admin的路由,我当时唰一下脸就白了,当时就觉得这个逼不讲武德,细细想来我只添加了路由而没有删除路由,这时的我脑海中想到了两个办法,一个是利用上面提到过的刷新初始化路由的方法,只需要登出后location.reload()一下就能解决问题,就是用户看起来不优雅。二就是使用router.removeRoute()方法将之前添加的路由使用for of方法删除,就是麻烦一点。想到这时我忍不住看了一眼后面的测试小姐姐,算了算了还是第二种方法吧。于是我在pinia中定义了一个专门用来删除路由的方法cleanRoute,在每次登陆失效或者登出的时候调用达到清除上一个账户添加的路由。