在正式的案例中,我们需要登录后从服务器获取token后再用token来获取数据,而且对于用户也有不同的角色(管理员和普通用户),因此实际项目的路由应该根据权限进行动态获取,下面就对之前实现的后台管理项目进行修改,将静态路由修改成动态路由。
首先增加本地mock数据仓库,封装api:
//本地mock模拟数据
const adminMenu = [
{
path: '/adminhome',
name: 'adminhome',
meta: {
label: '管理员主页',
icon: 'HomeFilled',
isShow: true,
},
url: "home/AdminHome"
},
{
path: '/manage1',
name: 'manage1',
meta: {
label: '管理页面1',
icon: 'Setting',
isShow: true,
},
url: "Admin/Manage1"
},
{
path: '/manage2',
name: 'manage2',
meta: {
label: '管理页面2',
icon: 'Setting',
isShow: true,
},
url: "Admin/Manage2"
},
];
const userMenu = [
{
path: '/userhome',
name: 'userhome',
meta: {
label: '用户主页',
icon: 'HomeFilled',
isShow: true,
},
url: "home/UserHome"
},
{
path: '/userPage1',
name: 'userPage1',
meta: {
label: '页面1',
icon: 'Setting',
isShow: true,
},
url: "User/UserPage1"
},
{
path: '/userPage2',
name: 'userPage2',
meta: {
label: '页面2',
icon: 'Setting',
isShow: true,
},
url: "User/UserPage2"
},
];
export default {
getMenuDataByRole: (params) => {
// console.log("==========Menu Mock=============");
// console.log(params);
let requestData = JSON.parse(params.body); //传入数据是json
let rsList = [];
// console.log("requestData.role: " + requestData.role);
if (requestData.role === "admin") {
rsList = adminMenu;
}
else {
rsList = userMenu;
}
return {
code: 200,
data: {
routers: rsList
}
}
},
}
然后在登录页面实现登录逻辑,并获取服务器返回的token和role并进行存储,本项目将之存储与vuex中,实际可以存储在cookie或者localstorage中实现登录状态保存等功能,然后就需要修改路由导航:
"use strict";
import { ref } from "vue";
import { createRouter, createWebHashHistory, } from 'vue-router'
import store from '../store/index'
import api from '../api/api';
let inited = false; //是否加载过
const routes = [
{
path: '/',
name: "login",
component: () => import('../views/login/Login.vue')
},
{
path: '/main',
name: 'main',
component: () => import(/* webpackChunkName: "[main]"*/'../views/Main.vue')
},
]
const router = createRouter({
history: createWebHashHistory(),//调用
routes
})
// 路由拦截与动态路由
router.beforeEach(async (to) => {
// console.log("==============Router===============");
// 登录拦截
const token = store.state.userToken;
// console.log("token: " + token);
if (!token && to.name !== "login") {
return '/';
}
if (to.name !== 'login' && token) {
if (!inited) { //还未动态加载路由
//动态路由
const role = store.state.userRole;
let routerData = ref([]);
// const { proxy } = getCurrentInstance();
let resObj = await api.getMenuData({ role: role });
routerData = resObj.routers;
// console.log(routerData);
routerData.forEach((v) => {
let viewUrl = `../views/${v.url}.vue`;
// console.log(viewUrl);
let routerObj = {
path: v.path,
name: v.name,
meta: v.meta,
component: () => import(/* @vite-ignore *//* webpackChunkName: "[request]"*/ viewUrl),
}
// console.log(routerObj);
router.addRoute("main", routerObj);
})
// console.log(routerData);
inited = true;
// router.replace(to.name)
console.log();
}
}
else {
inited = false;
}
});
export default router; //导出路由
上述的逻辑是,使用一个是否进行了路由列表初始化的标键变量inited来进行标键是否进行了路由表的初始化,然后先拦截非登录的访问页面请求,再根据role来向服务器请求对应的路由列表。
注意!!!在动态import时vite会给我们抛出警告,这里我确保url正确,所以采用/* @vite-ignore */注释忽略了,实际参考下面可以解决。
vue3+vite2警告提示The above dynamic import cannot be analyzed by vite问题,vite中import动态引入_云秒的博客-CSDN博客