从后端获取路由数据,将该请求放置在路由守卫(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