1、保存路由信息
在登录的时候从后端获取路由信息保存到全局pinia或者是vuex,我用的是pinia
建议在保存的时候对路由信息数组做好处理
2、在router.ts中引入pinia保存的路由信息:
注意不要使用createWebHistory路由模式,不然上线后刷新会空白,需要使用hash模式
import {
createRouter,
RouteRecordRaw,
createWebHashHistory,
} from "vue-router"
//全局保存的路由信息
import { menusRouterStore } from "@/stores/modules/menusRouter"
//确保打包后动态导入vue文件
const modules = import.meta.glob("../views/**/**.vue")
const routes: RouteRecordRaw[] = [
{
path: "/",
redirect: "/home",
},
]
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes,
})
3、添加动态路由+再次加载路由
目前路由只有静态的页面,我们需要做动态路由,需要在路由守卫router.beforeEach中添加。
router.beforeEach((to, from, next) => {
const allow = Session.get("token")
const menus = menusRouterStore().menus
NProgress.start()
//判断是否有token
if (!allow && to.path !== "/login") {
next("/login")
} else {
//如果有动态路由就添加
if (menus.length) {
menus.forEach((item: any) => {
router.addRoute("Home", {
component: modules[`${item.component}`],
name: item.name,
path: item.path,
meta: item.meta,
})
})
}
if (to.matched.length === 0 && !menusRouterStore().isAddAgain) {
// 再次加载路由
menusRouterStore().setisAddAgain(true)
//判断是否有路由 在追加一次
menus.forEach((item: any) => {
router.addRoute("Home", {
component: modules[`${item.component}`],
name: item.name,
path: item.path,
meta: item.meta,
})
})
next({ ...to, replace: true })
} else if (to.matched.length === 0 && menusRouterStore().isAddAgain) {
//跳转到404
next("/404")
} else {
next()
}
}
})
注:这里会衍生出一个问题,第一次登录的时候,路由信息没加进去,会跳404,所以这里需要做一个判断,判断路由to.matched这个去哪里的路由信息数组有没有数据,没有就再次添加动态路由信息,还有这块需要添加一个全局标识isAddAgain是否需要重新加载路由
4、全局数据
import { defineStore } from "pinia"
export const menusRouterStore = defineStore("menusRouter", {
state: () => {
return {
menus: [],
isAddAgain: false, //是否再次添加 false表示还没有再次添加
}
},
actions: {
setMenusRouter(data: any) {
this.menus = data
},
setisAddAgain(data: any) {
this.isAddAgain = data
},
},
persist: {
storage: sessionStorage,
},
})
5、路由刷新问题
动态路由添加后,每次刷新页面空白,这是因为刷新后路由守卫没再次走一遍,这里就需要在App.vue里面做判断,重新添加路由信息并跳转刷新前路由
import { useRouter } from "vue-router"
import { menusRouterStore } from "@/stores/modules/menusRouter"
const modules = import.meta.glob("../views/**/**.vue");
const router = useRouter()
const menus = menusRouterStore().menus;
if (menus.length) {
//更改是否再次加载路由标识
menusRouterStore().setisAddAgain(false);
//添加动态路由信息
menus.forEach((item: any) => {
router.addRoute("Home", {
component: modules[`${item.component}`],
name: item.name,
path: item.path,
meta: item.meta,
})
})
router.isReady().then(() => {
//获取刷新前路由
const url =window.location.href.split('#')[1];
//重新跳转
router.push(url)
})
}