有没有办法以简单的方式重建应用程序导航路线?

时间:2017-03-15 16:28:55

标签: angular typescript angular2-routing

我目前正在开发一种通用方法,可以从应用程序的所有路径为用户构建导航面板。

到目前为止,我找到了一个可行的解决方案,但这涉及到我的路线和大量代码中添加数据。我想知道是否会有更简单的解决方案。

首先,这是我的(减少的)路线:

master-routing.module.ts

const routes: Routes = [
  {
    path: '',
    component: MasterComponent,
    canActivate: [AuthGuard, RoleGuard],
    data: {
      roles: ['user'],
      displayRoute: true,
      frenchName: 'General',
      englishName: 'General',
      materialIcon: 'view_headline'
    },
    resolve: {
      currentUser: CurrentUserResolver
    },
    children: [
      {
        path: 'dashboard',
        component: DashboardComponent,
        data: {
          displayRoute: true,
          frenchName: 'Dashboard',
          englishName: 'Dashboard',
          materialIcon: 'dashboard'
        },
      },
      {
        path: 'equipments',
        loadChildren: 'app/equipments/equipment.module#EquipmentModule',
        data: {
          displayRoute: true,
          frenchName: 'Equipements',
          englishName: 'Equipments',
          materialIcon: 'clear'
        }
      }
    ]
  }
];

equipment-routing.module.ts

const routes: Routes = [
  {
    path: 'manage',
    component: ManageEquipmentsComponent,
    data: {
      displayRoute: true,
      moduleName: 'equipments',
      frenchName: 'Importer des équipements',
      englishName: 'Import equipments',
      materialIcon: 'settings_remote'
    }
  },
];

正如你所看到的,我有一个延迟加载模块的子路由,这个模块定义了自己的路由。

令人头疼的是:

我的MasterComponent链接到2个组件:HeaderComponent,它允许我搜索我的路线,NavBarComponent,显示我的应用程序的主要路线和子路线。这就是我需要的:

  • 构建路由的方法,以便我的子路由也可以显示来自延迟加载的模块
  • 我可以发送到Array的{​​{1}}个已构建路线,以便我可以从HeaderComponentfrenchName
  • 搜索我的路线
  • englishName类似于Tree的路线,因此我可以显示我可以发送到router.config的基本路线及其子路线。

以下是获取NavBarComponent已构建路径的代码:

master.component.ts

Array

master.component.ts(第1部分)

parentModules: ParentModule[] = [];
navigableRoutes: RouteDisplay[] = [];


constructor(
  private router: Router,
  private identityService: IdentityService,
  private authService: AuthService,
  private applicationsService: ApplicationsService
) { }

ngOnInit() {
  this.getRoutesToDisplay(this.router.config);
  console.log('navigableRoutes => ', this.navigableRoutes);
  this.navigationTree = this.buildNavigationTree(this.navigableRoutes);
  console.log('navigationTree => ', this.navigationTree);
}

需要注意的事项:

  • 我使用路线数据中的 /** * Recursively builds the application navigation from the router config * @param {Route[]} routeNode Current node routes to browse * @param {string} parent Parent of the current routeNode * * @see Doesn't manage duplicate routes */ getRoutesToDisplay(routeNode: Route[], parent?: string): void { let currentParent: string = (parent != null) ? parent : null; routeNode.forEach((route: RouteConfig) => { let pathFormatter: string = ''; // Paths with Ids if (!route.path.includes(':')) { // Manage module routes if (route.loadChildren) { this.parentModules.push({ path: route.path, parent: currentParent }); } // Checks if the route is to be displayed if (route.data && route.data.displayRoute && route.data.frenchName && route.data.englishName && route.data.materialIcon && ((route.data.roles && this.identityService.hasRole(route.data.roles)) || !route.data.roles)) { if (route.data.moduleName) { // Get the matching parent Module if the current path has one (there can be only one); let parentModule = this.parentModules.filter(module => { return module.path === route.data.moduleName; })[0]; // Manage empty paths for lazy-loaded child routes if (currentParent == null) { currentParent = ''; } // If there is a parentModule found AND the currentParent doesn't contain the module (for child cases) if (parentModule && currentParent != null && !currentParent.includes(parentModule.path)) { currentParent = String.prototype.concat(parentModule.parent, '/', parentModule.path); } } // Builds the path format if there is a parentNode if (currentParent != null) { pathFormatter = pathFormatter.concat(currentParent, '/', route.path); } this.navigableRoutes.push({ path: pathFormatter ? pathFormatter : route.path, parent: currentParent, frenchName: route.data.frenchName, englishName: route.data.englishName, materialIcon: route.data.materialIcon, moduleName: route.data.moduleName ? route.data.moduleName : '', loadChildren: route.loadChildren ? route.loadChildren : '', }); } } // Start a new nodeSearch on the child routes and sets the parentNode if (route.children && route.children.length > 0) { this.getRoutesToDisplay(route.children, pathFormatter ? pathFormatter : route.path); } }); } 来选择何时显示我的路线。
  • 我使用路由数据中的displayRoute将此路由链接到相应的延迟加载模块路径名

以下是输出:

master.component.ts(第二部分)

moduleName

master.component.ts(第3部分和最后部分)

  navigationTree: RouteTreeDisplay[] = [];
  isFirstLevelDone = false;

  ...

  /**
  * Builds the NavigationTree from the navigable routes recursively built
  * @param {RouteDisplay[]} navigableRoutes Node of navigable routes routes to browse
  * @returns {RouteTreeDisplay[]} Tree of RouteTreeDisplay
  */
  buildNavigationTree(navigableRoutes: RouteDisplay[]): RouteTreeDisplay[] {
    let navigableRoutesCopy: RouteDisplay[] = Object.assign([], navigableRoutes);
    let navigationTree: RouteTreeDisplay[] = [];

    // Build treeRoots
    let navigationTreeRoots: RouteTreeDisplay[] = [];
    navigableRoutesCopy.forEach((route: RouteDisplay) => {
      // Set lazy-loaded module routes as TreeRoots
      let isLazyLoadedModuleRoute = navigationTree.filter((treeRoot: RouteTreeDisplay) => route.loadChildren && treeRoot.path === route.parent).length > 0;

      // Define TreeRoots
      if ((route.parent == null && !route.moduleName) || isLazyLoadedModuleRoute) {
        let treeRoot: RouteTreeDisplay = {
          path: route.path,
          children: [],
          englishName: route.englishName,
          frenchName: route.frenchName,
          materialIcon: route.materialIcon
        };
        navigationTree.push(treeRoot);
        navigationTreeRoots.push(treeRoot);
      }
    });

    // Clear treeRoots from the navigableRoutes
    navigableRoutesCopy = navigableRoutesCopy.filter(baseRoute => navigationTreeRoots.find(treeRoot => treeRoot.path === baseRoute.path) ? false : true);

    while (navigableRoutesCopy.length > 0) {
      navigableRoutesCopy = this.buildTreeChilds(navigationTree, navigableRoutesCopy);
    }

    // Delete empty treeRoots
    navigationTree = navigationTree.filter((treeRoots: RouteTreeDisplay) => treeRoots.children && treeRoots.children.length > 0);

    return navigationTree;
  }

以下是输出:

1 个答案:

答案 0 :(得分:0)

您可以在单独的ts模块中构建路由,并从该模块导出路由配置。然后,在功能路由模块中,您可以导入该路由配置并在延迟加载的功能模块配置中使用它。

您只需要小心放在该路由配置模块中的内容 - 确保您没有从功能模块中引用任何类型,以确保您的模块捆绑包最终不会包含您的功能模块的部分内容你主要的,急切的装束。

至于使用该路由配置来构建导航 - 我没有详细检查您的代码 - 我认为您有正确的想法循环路由配置并包含根据路由定义的链接。