vue3中的动态路由设置和路由守卫
动态路由设置和路由守卫
·
一、路由全局前置守卫设置。
permission.ts:
1、先判断是否有token。
没有token: 可以访问白名单页面;但未登录如果要去的不是白名单页面,让他到登录页面,然后再重定向到要去的页面。
有token(即登录成功):如果要去登录页,直接跳转;如果要去其他页面,
2、要先判断是否有用户信息—有用户信息:如果没有从已有的所有路由中匹配到路由,有从上个路由过来的就直接跳到上个路由,否则就跳到401;没有用户信息:先通过store获取用户信息,根据用户角色来获取并添加动态路由
import { RouteRecordRaw } from "vue-router"; //这行代码是使用 vue-router 库在 Vue.js 应用程序中定义路由所必需的。 RouteRecordRaw 接口用于定义 Vue.js 应用程序中的路由。
import { defineStore } from "pinia";
import {constantRoutes} from '@/router'; //拿到路由文件里的静态路由
import {listRoutes} from '@/api/system/menu'; //拿到路由api
import router from '@/router';
import NProgress from 'nprogress';
import useStore from '@/store';
import { RouteRecord } from 'vue-router';
NProgress.configure({ showSpinner: false }); //进度环显示/隐藏
// import.meta.glob 函数从文件系统导入多个模块
const modules = import.meta.glob('../../views/**/**.vue');
//白名单
const whiteList = ['/login', '/auth-redirect' ];
//路由全局前置守卫
router.beforeEach(async (to, from, next) => {
NProgress.start();//进度条开始
const { user, permission, app } = useStore();
const hasToken = user.token;
// 1.路由跳转前先判断是否有token
if (hasToken) {
// 1.1登录成功,跳转到首页
if (to.path === '/login') {
next({path: '/'});
NProgress.done();
} else {
// 1.2登录成功,去其他页面----要判断是否有用户信息
const hasGetUserInfo = user.roles.length > 0;
//有用户信息
if (hasGetUserInfo) {
// 1.2.1如果没有从已有的所有路由中匹配到路由,有从上个路由过来的就直接跳到上个路由,否则就跳到401
if (to.matched.length === 0) {
// next({name: ''})----通过名称导航到特定路由。name: 是我要导航到的路由名称
from.name ? next({name: from.name as any }) : next('/401');
} else {
next();
}
} else { // 1.2.2 登录成功但 没有用户信息----先通过store获取用户信息,根据用户来获取并添加动态路由
try {
await user.getUserInfo();
const roles = user.roles;
//通过获取到的角色拿到相应角色的动态路由信息
const accessedRoutes: any = await permission.generateRoutes(roles);
accessedRoutes.forEach((route:any) => {
//将动态路由里的每个路由添加进去
router.addRoute(route);
});
// 将当前路由信息与replace:true合并为一个新的对象,这个新的对象会被传入到next函数中。
// 表示要跳转到一个新的路由,并且使用replace模式进行跳转---会替换当前的路由记录,而不是添加一条新的记录。
next({...to, replace:true});
} catch (error) {//登录成功但获取用户信息失败----要移除token并跳转到登录页
await user.resetToken();
ElMessage.error((error as any) || 'Has Error');
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
}
} else { //2.没有token的话可以访问白名单页面(登录页面)
// indexOf: 返回数组中第一次出现给定元素的下标,如果不存在就返回-1
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
// 未登录但要去的不是白名单页面-----让他到登录页面,然后再重定向到要去的页面
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
})
二、根据用户角色来筛选获取并添加动态路由
store下的permission.ts:
const usePermissionStore = defineStore({
id:'permission',
state: ():PermissionState => ({
routes: [], //总共的路由
addRoutes: [], //动态添加的路由
}),
actions: {
setRoutes(routes: RouteRecordRaw[]) {
this.addRoutes = routes;
this.routes = constantRoutes.concat(routes);
},
// 根据角色筛选得到的动态路由 重要一步!
generateRoutes(roles: string[]){
return new Promise((resolve, reject) => {
//从接口获取路由列表
listRoutes().then((response) => {
const asyncRoutes = response.data;//从接口获取的所有路由
const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);//根据角色筛选得到的动态路由 重要一步!
this.setRoutes(accessedRoutes); //把获得的动态路由给store赋值
resolve(accessedRoutes);
}).catch((error) => {
reject(error)
})
})
}
}
})
export default usePermissionStore;
//根据角色过滤所有路由生成动态路由
export const filterAsyncRoutes = (routes:RouteRecordRaw[], roles: string[]) => {
// 对每一个路由进行遍历
routes.forEach((route) => {
//定义一个空数组----放过滤出来的动态路由
const res: RouteRecordRaw[] = [];
//拿到每一个路由项并对里面的属性进行解构
const tmp = {...route} as any;
//如果这个角色有这个路由权限就说明可以访问路由
if (hasPermission(roles, tmp)) {//此角色可以访问路由后就要配置路由信息了
if (tmp.component == 'Layout') {
tmp.component = Layout;
} else {
//如果不是Layout组件,拿到其他组件名称
const component = modules[`../../views/${tmp.component}.vue`] as any;
if (component) {
tmp.component = modules[`../../views/${tmp.component}.vue`];
} else {
//如果这个组件不存在 就跳到404页面
tmp.component = modules[`../../views/error-page/404.vue`]
}
}
res.push(tmp);
if(tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles);
}
}
});
return res;
}
//对某个角色是否对某个路由拥有权限进行判断------ 根据不同角色判断路由是否存在
const hasPermission = (roles: string[], route: RouteRecord) => {
if(route.meta && route.meta.roles) {
//如果是管理员--肯定有权限
if(roles.includes('ROOT')) {
return true;
}
//如果不是管理员
return roles.some((role) => {
if(route.meta?.roles !== undefined) {
//实例路由里面的roles里包含实际登录的用户role--返回true,说明这个用户有路由权限
return (route.meta.roles as stirng[]).includes(role);
}
})
}
return false;
}
更多推荐
已为社区贡献2条内容
所有评论(0)