这个vue3动态路由访问不了?

我想写一个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())已经看到路由已经添加了进去,但是浏览器访问对应的路由显示空白,报错提示没有匹配的路由,这是哪个地方有问题?

阅读 2.6k
1 个回答

从你上面的代码来看,你在router.beforeEach钩子函数中调用了loadRoutes(),这样会在每次路由跳转之前去加载路由。但是,因为getMenus()是异步操作,loadRoutes()还没有完成添加路由的操作,就执行了next(),导致在路由跳转之前,新的路由还没有被添加到路由表里,所以会出现你说的空白页面的问题。

你可以在loadRoutes()函数中返回一个Promise,还有在router.beforeEach里等待loadRoutes()函数执行完毕后再调用next()。这些地方改一下:

// 修改 loadRoutes 
function loadRoutes() {
  return new Promise((resolve) => {
    getMenus().then((res) => {
      addRoute(res.data.menus);
      console.log(router.getRoutes());
      resolve();
    });
  });
}

// 修改 router.beforeEach 
router.beforeEach(async (to, from, next) => {
  await loadRoutes();
  next();
});

然后,为了不让每次路由跳转时都去请求路由数据,你可以在loadRoutes函数中判断是否已经加载过路由,如果已经加载过,就不再重新加载:

let isRoutesLoaded = false; // 添加一个标识,初始值为 false

// 修改 loadRoutes 函数
function loadRoutes() {
  return new Promise((resolve) => {
    if (isRoutesLoaded) {
      resolve();
      return;
    }

    getMenus().then((res) => {
      addRoute(res.data.menus);
      console.log(router.getRoutes());
      isRoutesLoaded = true; // 路由加载完成后,将标识设为 true
      resolve();
    });
  });
}

这样只有在第一次访问页面时才会去加载动态路由,之后的路由跳转不会再次加载。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏