vue-router addRoute()刷新白屏,404坑

1,702 阅读1分钟

记录一次vue-router异步加载路由踩的坑。

1.加载路由配置代码

// 白名单应该包含基本静态路由
const WHITE_NAME_LIST: string[] = [];
export const getRouteNames = (array: any[]) =>
  array.forEach((item) => {
    WHITE_NAME_LIST.push(item.name);
    getRouteNames(item.children || []);
  });
getRouteNames(basicRoutes);
/**
 * 重置路由
 */
export function resetRouter() {
  // 应用配置
  const { router } = appOptions;
  router.getRoutes().forEach((route) => {
    const { name } = route;
    if (name && !WHITE_NAME_LIST.includes(name as string)) {
      if (router.hasRoute(name)) router.removeRoute(name);
    }
  });
}
export function loadRoutes(rConfig?: Array<menuDItem>) {
  // 清空以前的路由
  resetRouter();
  const accountStore = useAccountStore();
  // 应用配置
  const { router } = appOptions;

  let routesConfig: Array<menuDItem> = [];

  // 如果 routesConfig 有值,则更新到本地,否则从本地获取
  if (rConfig) accountStore.setRoutesConfig(rConfig);
  routesConfig = rConfig ?? accountStore.getRouesConfig;
  // 加载异步路由配置
  if (routesConfig && routesConfig.length > 0) {
    let routes = parseRoutes(routesConfig, asyncRoutes); // 解析路由函数
    routes = formatRoutes(routes); // 格式化路由函数
    routes.forEach((route) => {
      router.addRoute('layout', route);
    });
    router.options.routes[0].children = routes;
  }
  // 必须最后加上404跳转路由,不然刷新会直接跳转404
  router.addRoute({
    path: '/:pathMatch(.*)',
    name: '*',
    meta: { hidden: true },
    redirect: '/404',
  });
  // 初始化Admin后台菜单数据
  const rootRoute = router.options.routes.find((item) => item.path === '/');
  const menuRoutes = rootRoute && rootRoute.children;
  if (menuRoutes) {
    setting().setMenuData(menuRoutes);
  }
}

2.main.ts代码

import { router } from '@/router/index';
import { loadRoutes, setAppOptions } from '@/utils/routerUtil';
app.use(router);
// 设置应用配置
setAppOptions({ router });
loadRoutes();

3.router.beforeEach重新加载页面代码

router.beforeEach((to, from, next) => {
  if (to.matched.length === 0) { // 刷新页面第一次进入页面时,addRoute刚添加路由进去,但没有成功加载需要重进一次
    next({ 
        ...to, 
        replace: true // 重进一次, 不保留重复历史
    });
  } else { // 重进一次后成功加载对应路由,直接next(),防止路由无限循环
    next();
  }
});