You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Angular菜单所有路由(含懒加载节点)获取静态data信息?

解决Angular获取全路由树(含懒加载)的moduleId问题

方法一:预加载所有懒加载模块后遍历路由树

Angular的Router服务默认不会加载懒加载模块的路由元数据,所以可以先通过预加载策略加载所有懒加载模块,再递归遍历完整路由配置。

1. 实现全量预加载策略

创建自定义预加载类,强制加载所有懒加载模块:

import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';

export class PreloadAllModules implements PreloadingStrategy {
  preload(route: Route, load: () => Observable<any>): Observable<any> {
    return route.loadChildren ? load() : of(null);
  }
}

在AppModule中注册该策略:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PreloadAllModules } from './preload-all-modules';

const routes: Routes = [/* 你的路由配置 */];

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: PreloadAllModules
  })],
  exports: [RouterModule],
  providers: [PreloadAllModules]
})
export class AppRoutingModule { }

2. 递归提取所有moduleId

写一个工具函数遍历路由树,收集所有moduleId:

import { Router, Route } from '@angular/router';

export function getAllModuleIds(router: Router): string[] {
  const moduleIds: string[] = [];

  function traverseRoutes(routes: Route[]) {
    routes.forEach(route => {
      // 提取当前路由的moduleId
      if (route.data?.moduleId) {
        moduleIds.push(route.data.moduleId);
      }
      // 递归处理常规子路由
      if (route.children) {
        traverseRoutes(route.children);
      }
      // 处理已加载的懒加载路由子节点
      if (route._loadedRoutes) {
        traverseRoutes(route._loadedRoutes);
      }
    });
  }

  traverseRoutes(router.config);
  return moduleIds;
}

在组件中使用(等待预加载完成后获取):

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { getAllModuleIds } from './route-utils';

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html'
})
export class MenuComponent implements OnInit {
  moduleIds: string[] = [];

  constructor(private router: Router) { }

  ngOnInit(): void {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        this.moduleIds = getAllModuleIds(this.router);
        // 此处可根据moduleId处理菜单显隐逻辑
      }
    });
  }
}

方法二:不预加载,动态解析懒加载路由配置

如果不想提前加载所有模块,可以手动加载懒加载模块的路由配置,避免加载组件逻辑。

1. 动态获取懒加载路由配置

写一个函数解析懒加载模块的路由:

import { Route } from '@angular/router';

async function loadLazyRouteConfig(route: Route): Promise<Route[]> {
  if (!route.loadChildren) return [];

  // 兼容loadChildren的字符串和函数两种格式
  let moduleRoutes: Route[] = [];
  if (typeof route.loadChildren === 'string') {
    const [modulePath, moduleName] = route.loadChildren.split('#');
    const module = await import(`../${modulePath}`);
    moduleRoutes = module[moduleName].routes;
  } else {
    const module = await route.loadChildren();
    moduleRoutes = module.default.routes;
  }
  return moduleRoutes;
}

2. 异步遍历全路由树

修改遍历函数,动态加载懒加载路由并收集moduleId:

import { Router, Route } from '@angular/router';

export async function getAllModuleIdsAsync(router: Router): Promise<string[]> {
  const moduleIds: string[] = [];

  async function traverseRoutes(routes: Route[]) {
    for (const route of routes) {
      if (route.data?.moduleId) {
        moduleIds.push(route.data.moduleId);
      }

      // 处理常规子路由
      if (route.children) {
        await traverseRoutes(route.children);
      }

      // 处理懒加载路由
      if (route.loadChildren) {
        const lazyRoutes = await loadLazyRouteConfig(route);
        await traverseRoutes(lazyRoutes);
      }
    }
  }

  await traverseRoutes(router.config);
  return moduleIds;
}

在组件中调用:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { getAllModuleIdsAsync } from './route-utils';

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html'
})
export class MenuComponent implements OnInit {
  moduleIds: string[] = [];

  constructor(private router: Router) { }

  async ngOnInit(): void {
    this.moduleIds = await getAllModuleIdsAsync(this.router);
    // 处理菜单显隐逻辑
  }
}

额外建议

如果菜单结构是固定预定义的,也可以单独维护一份菜单配置数组,直接包含moduleId和对应路由路径,不需要从路由配置中解析,这种方式更简单可靠,适合菜单结构不常变动的场景。

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:32:55