我目前正在开发一种通用方法,可以从应用程序的所有路径为用户构建导航面板。
到目前为止,我找到了一个可行的解决方案,但这涉及到我的路线和大量代码中添加数据。我想知道是否会有更简单的解决方案。
首先,这是我的(减少的)路线:
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}}个已构建路线,以便我可以从HeaderComponent
或frenchName
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;
}
答案 0 :(得分:0)
您可以在单独的ts模块中构建路由,并从该模块导出路由配置。然后,在功能路由模块中,您可以导入该路由配置并在延迟加载的功能模块配置中使用它。
您只需要小心放在该路由配置模块中的内容 - 确保您没有从功能模块中引用任何类型,以确保您的模块捆绑包最终不会包含您的功能模块的部分内容你主要的,急切的装束。
至于使用该路由配置来构建导航 - 我没有详细检查您的代码 - 我认为您有正确的想法循环路由配置并包含根据路由定义的链接。