我想写一个vue3动态路由的demo,写完之后,在浏览器上访问/home或者/system均是白屏,只有/login是可以正常访问的,这段代码到底是哪里出现了问题?
这是我的路由数据:
Mock.mock("/getMenus", "get", {
status: 200, //请求成功状态码
menus: [
{
path: "/",
name: "Main",
component: "MainView",
redirect: "home",
children: [
{
path: "home",
name: "home",
component: "HomeView",
meta: {
title: "首页",
icon: "HomeFilled",
},
},
],
},
{
path: "/system",
name: "system",
component: "SystemView",
meta: {
title: "首页",
icon: "HomeFilled",
},
}
],
});
这是我的代码:
import { createRouter, createWebHistory } from "vue-router";
import { getMenus } from "../api/getMenu.js";
const routes = [
{
path: "/login",
name: "login",
component: () => import('../views/LoginView.vue'),
},
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
});
function formatRoute(r) {
if (r.children && r.children.length > 0) {
let result = {
path: r.path,
name: r.name,
component: () => import(`../views/${r.component}.vue`),
children: []
}
r.children.forEach(item => {
let child = {
path: item.path,
name: item.name,
component: () => import(`../views/${item.component}.vue`),
meta: item.meta
}
result.children.push(child)
})
return result
} else {
return {
path: r.path,
name: r.name,
component: () => import(`../views/${r.component}.vue`),
}
}
}
function addRoute(data) {
data.forEach(item => {
let r = formatRoute(item)
router.addRoute(r)
})
}
router.beforeEach((to, from, next) => {
loadRoutes()
next()
});
function loadRoutes(){
getMenus().then(res => {
addRoute(res.data.menus)
console.log(router.getRoutes())
});
}
export default router;
控制台打印console.log(router.getRoutes())已经看到路由已经添加了进去,但是浏览器访问对应的路由显示空白,报错提示没有匹配的路由,这是哪个地方有问题?
从你上面的代码来看,你在router.beforeEach钩子函数中调用了loadRoutes(),这样会在每次路由跳转之前去加载路由。但是,因为getMenus()是异步操作,loadRoutes()还没有完成添加路由的操作,就执行了next(),导致在路由跳转之前,新的路由还没有被添加到路由表里,所以会出现你说的空白页面的问题。
你可以在loadRoutes()函数中返回一个Promise,还有在router.beforeEach里等待loadRoutes()函数执行完毕后再调用next()。这些地方改一下:
然后,为了不让每次路由跳转时都去请求路由数据,你可以在loadRoutes函数中判断是否已经加载过路由,如果已经加载过,就不再重新加载:
这样只有在第一次访问页面时才会去加载动态路由,之后的路由跳转不会再次加载。