设计流程
1.准备一个请求,从后端获取路由数据
2.这个请求放置在路由守卫(router.beforeEach)next的前面,阻塞next(),当动态组件添加好了在进入页面。
import { createRouter, createWebHistory } from 'vue-router' // 基础路由 一般回放一个Login页面的对象 import { baseRoutes } from '@/router/basicRoutes' import { getUsermMenu } from "@/api"; // 在js/ts里面使用pinia,需要这么使用,多导出一个Pinia,这里就不展开说了,大家自行百度 import { routerListAddCountStore, routerListStore } from '@/stores/index' import pinia from '@/stores/index' const routerListAddCountV = routerListAddCountStore(pinia) const routerListStoreV = routerListStore(pinia) // 创建路由对象 let router = createRouter({ // 路由模式hash // history: createWebHashHistory(), history: createWebHistory(), routes: [...baseRoutes] }) // 配置路由守卫 router.beforeEach((to, from, next) => { // routerListAddCountV.routerListAddCount 控制整个项目只会请求一次后端路由 (请求后这个Pinia+=1就行了,简单判断) // routerListAddCountV.routerListAddCount 是 pinia if (routerListAddCountV.routerListAddCount >= 1) { console.log('我走不请求数据') next() } else { console.log('我走请求数据') // 这个是后端请求路由 // !!!!!第一个知识点来了,如果你想阻塞next,你必须使用.then的方式调用,将next,放在.then中,看别人是这么解释的,next只能放在同步逻辑中,你写settiomeout 和 async await是不行的。 getUsermMenu().then(res => { // 路由 let TempRouterList = res.data.menuList // !!!!第二个知识点来了,我们的路由都是使用懒加载的,但是后端直接传过来()=》一个箭头函数是不能用的,所以我们要使用vue3(vite)的写法import.meta.glob,注意webpack不是这么写的,webpack的话需要自己去查一下。 // ../views/*/*.vue 这个的意思就是会将views/任意/任意.vue 复合这个格式的vue转换成箭头函数 const modules = import.meta.glob(['../views/*/*.vue', '../views/*/*/*.vue']) // 这一段代码的意思就是 TempRouterList.forEach(element => { // 具体的xi // 拆解一下 element.component是后端传过来的,是 '/home/layout.vue' // 加上 ../views 相当与是补全一下 ,这里用../(相对路径) 是因为不能写@(绝对路径) // 最后打印 element.component 出来是 () => import("/src/views/home/layout.vue") 是这样的 element.component = modules[`../views${element.component}`] if (element?.children.length > 0) { // 如果有嵌套路由也记得 懒加载一下 element.children.forEach(Sonelement => { Sonelement.component = modules[`../views${Sonelement.component}`] }) } // !!!!第三个知识点, router就是上面创建的router 一页代码直接使用, 我们先说addRoute这个方法。就是将这个路由关系加进去我们路由的一个方法,添加一个最大的父级即可 router.addRoute(element) }); // !!!第四个知识点,404页面必须放在我们动态拿来的数据后面,如果放在前面会先匹配404 let Route404 = { path: '/404', component: modules[`../views/404/index.vue`], name: '404',//命名路由 meta: { // 增加 title: '丢失页面', show: false } } // 找不到的页面 let ANyRoute = { path: '/:pathMatch(.*)*', redirect: '/404', name: 'Any', meta: { // 增加 title: '任意', show: false } } router.addRoute(Route404) router.addRoute(ANyRoute) TempRouterList.push(Route404) TempRouterList.push(ANyRoute) // 这个是将我们编辑好的这个路由数组,加入到pinia中,渲染的左侧菜单的时候使用这个Pinia就行 routerListStoreV.setRouterList(TempRouterList) // 这个就是最开始判断》=1的哪个逻辑,这里面其实就是个pinia,pinia的方法是 +=1,这样加载过一次后,就会走不请求的判断 routerListAddCountV.setRouterListAddCount() // !!!第5个知识点, router.getRoutes() 可以获取到你最新addrouter的注册路由, router.opetion并不是最新的 let newRoutes = router.getRoutes() // 默认去第一个 let goUrl = newRoutes[0].path // 如果被注册就去注册的 newRoutes.some(item=>{ if(item.path == to.path){ goUrl = to.path return true } }) // !!!第6个知识点来了,当你使用addroute加入,并用光杆next(),是会白屏的!必须加上replace: true,这个官方的解释就是等路由更新好再跳转的意思。 next({ path: goUrl, replace: true }) }) } }); // 配置路由对象 export default router
这是最基础的逻辑,如果需要用到项目中,需要自行加上判断是是否有token,并跳转到Login页面等等