我将Angular 2.1用于具有多个子模块的大型应用程序,每个子模块定义按功能组织的子应用程序。顶级模块通过导入每个子应用程序的路由等,为整个应用程序配置RouterModule以及所有子路由。因此,从子应用程序的角度来看,它相对于顶层的任何路由进行路由。级别应用程序设置路由,但是子应用程序没有直接明确地知道它的主要路由实际是什么。
其中一些子应用程序具有在另一个子应用程序中更完全定义/控制的实体的摘要面板。从概念上讲,模块的设置如下:
Module 1:
Imports Module 2
Routes for Module 1
Component1A
App1View (contains Component1A, M2SummaryComponent)
Module 2:
Routes for Module 2 (one exported as APP2_VIEW_ROUTE, type Route)
Component2A
Component2B
M2SummaryComponent
App2View (contains Component2A, Component2B)
...etc.
我正在寻找一种设计模式,借此可以编写M2SummaryComponent链接到其自己模块中的路径,同时在模块1的App1View中实例化,而无需硬编码或重新组装以某种方式,手动路线。
我曾希望这是一个普遍存在的问题,Angular团队可能会使用像router.navigate([APP2_VIEW_ROUTE, ...other params])
这样的东西,其中一个人可以简单地传递用于配置与所需路径相关的RouterModule的路由对象。看一下源代码,但这似乎不是一个选择。相反,我们有ActivatedRoute的例子。
ActivatedRoute(下面的this.route
)面临的问题是它将与App1View相关。因此,尝试使用router.navigate(['m2SpecialId'],{relativeTo: this.route})
是一个非首发,因为它将相对于将我们带到App1View的路径,而不是返回到模块2的首选App2View路径。
就我所知,围绕这些问题的唯一其他的,有点优雅的路线(双关语)是使每个子应用程序的模块可以作为ModuleWithProviders导入,以便可选地,可以通知应用于其状态的顶级路由的模块。然后编写辅助函数,使用其定义的路由组合特定于该子应用程序的URI。
这感觉非常糟糕......就像框架中已经存在解决方案或设计模式一样,因此这个问题。
问题:
是否有使用Angular2路由器的设计模式,允许导入其他模块的组件干净地引用自己模块的预配置路由,同时保持灵活的顶级路由定义?
答案 0 :(得分:5)
如果要通过链接访问M1中的M2Component,则应使用RouterModule,不要在module1中导入module2。
在module1内部使用
RouterModule.forRoot([
{
path: 'module2',
loadChildren: 'path-of-module2/module2.module#Module2Module'
}
])
并在module2中
RouterModule.forChild([
{
path: '',
component: Module2Component
}
])
现在您可以从路线' / module2'。
打开Module2Component答案 1 :(得分:0)
这里的解决方案我说的听起来非常模板化。它要求您使用一对不透明的令牌设置子应用程序模块:一个用于您的URI,另一个用于防止重新配置该URI。
import {
NgModule,
OpaqueToken,
ModuleWithProviders,
Optional,
SkipSelf,
Inject
} from '@angular/core';
export const ROOT_URI = new OpaqueToken('ROOT_URI');
export const URI_GUARD = new OpaqueToken('URI_GUARD');
接下来,您需要定义NgModule
:
@NgModule({ /** ... as before ... */ })
export class SubApp1Module {
static configure(uri: string): ModuleWithProviders {
return {
ngModule: SubApp1Module,
providers: [
{ provide: ROOT_URI, useValue: uri },
{ provide: URI_GUARD, useFactory: provideGuard,
deps: [[ Object, new Optional(), new SkipSelf() ]] }
]
};
}
constructor(@Optional() @Inject(URI_GUARD) guard: any) { /** */ }
}
provideGuard
功能:
export function provideGuard(something: any): any {
if (!something) {
return 'guarded';
} else {
throw new Error('Do not attempt to configure this module more than once.');
}
}
在您要导入此模块并配置最终将您进入此子应用程序的RouterModule路由的模块中,您将其添加到导入:imports: [ ..., SubApp1Module.configure(SPECIAL_ROOT_URL), ...]
。
在SubApp1Module中的任何组件/指令中,您可以通过注入获取此模块的ROOT_URI
:
import { Inject } from '@angular/core';
import { ROOT_URI } from './whatever/local/export/location';
// Down at the constructor
constructor(@Inject(ROOT_URI) rootUri: string) {
console.log('This is my rootUri: ' + rootUri);
}
现在,这可行,当然您可以根据需要使用@Optional
或?
来允许注入默认值。如果您决定走这条路线,这也适用于注入解决路线的服务或工厂等。
在某些方面,这感觉就像Angular Way™(即,这样做)。然而,正如您所看到的那样,只是允许模块中的实体路由到他们自己的模块中,尽管在没有硬编码路径的情况下将其实例化为另一个模块中的Component,等等