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

作者站长头像
站长
· 阅读数 10

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

回复
1个回答
avatar
test
2024-07-04

从你上面的代码来看,你在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();
    });
  });
}

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

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容