实现过程:
-
/src/router/index.js动态添加路由;
-
permission.js 里动态添加路由方法
-
引入addRoutes() 方法,
-
如果用户登录成功了,就动态的添加进去,存储在vuex中;
-
解决刷新丢失路由,原因:是需要push() 或 replace() 方法手动的添加才不会丢失; hasNewRoutes ? next(to.fullPath) : next();
//src/router/index.js动态添加路由;
import { createRouter, createWebHashHistory } from "vue-router";
import index from "../pages/index.vue";
import NotFound from "@/pages/404.vue";
import login from "../pages/login.vue";
import Admin from "../layouts/admin.vue";
import GoodList from "../pages/goods/list.vue";
import CategoryList from "../pages/category/list.vue";
// 默认路由,所有用户共享
const routes = [
{
path: "/",
name: "admin",
component: Admin,
},
{
path: "/login",
name: "login",
component: login,
meta: {
title: "登录页",
},
},
{
path: "/:pathMatch(.*)*",
name: "NotFound",
component: NotFound,
},
];
// 动态路由,用于匹配菜单动态添加路由
const asyncRoutes = [
{
path: "/",
name: "/",
component: index,
meta: {
title: "后台首页",
},
},
{
path: "/goods/list",
name: "/goods/list",
component: GoodList,
meta: {
title: "商品管理",
},
},
{
path: "/category/list",
name: "/category/list",
component: CategoryList,
meta: {
title: "分类列表",
},
},
];
export const router = createRouter({
history: createWebHashHistory(),
routes,
});
// 动态添加路由的方法
export function addRoutes(menus) {
// 是否有新的路由
let hasNewRoutes = false;
const findAndAddRoutesByMenus = (arr) => {
arr.forEach((e) => {
let item = asyncRoutes.find((o) => o.path == e.frontpath);
if (item && !router.hasRoute(item.path)) {
router.addRoute("admin", item);
hasNewRoutes = true;
}
if (e.child && e.child.length > 0) {
findAndAddRoutesByMenus(e.child);
}
});
};
findAndAddRoutesByMenus(menus);
return hasNewRoutes;
}
permission.js 里动态添加路由方法
// 处理权限相关信息
import { router, addRoutes } from "@/router";
import { getToken } from "@/composables/auth";
import { toast, showFullLoading, hideFullLoading } from "./composables/util";
import store from "./store";
// 设置哪些页面是属于白名单的
const witheList = ["/login"];
function isWitheRoute(path) {
return witheList.includes(path);
}
// 全局前置守卫
router.beforeEach(async (to, from, next) => {
// 显示loading
showFullLoading();
const token = getToken();
// 判断如果是白名单就直接放行
if (isWitheRoute(to.path)) {
next();
return;
}
// 没有登录,强制跳转到登录页面
if (!token && to.path != "/login") {
toast("请先登录", "error");
next({ path: "/login" });
return;
}
//防止重复登录
if (token && to.path == "/login") {
toast("请无重复登录", "error");
return next({ path: from.path ? from.path : "/" });
}
// 如果用户登录了,自动获取用户信息,并存储在vuex中
let hasNewRoutes = false;
if (token) {
let { menus } = await store.dispatch("getinfo");
// 动态添加路由
hasNewRoutes = addRoutes(menus);
}
// 设置页面标题
let title = (to.meta.title ? to.meta.title : "") + "后台商城";
document.title = title;
hasNewRoutes ? next(to.fullPath) : next();
});
// 全局后置守卫
// 加载完成loading会自动关闭
router.afterEach((to, from) => hideFullLoading());