Angular 角度路由器:如何将数据传递到延迟加载模块?
我的Angular应用程序的模块有以下路由路径:Angular 角度路由器:如何将数据传递到延迟加载模块?,angular,lazy-loading,angular-routing,angular-module,angular-router,Angular,Lazy Loading,Angular Routing,Angular Module,Angular Router,我的Angular应用程序的模块有以下路由路径: @NgModule({ imports: [ RouterModule.forChild([ { path: 'documents', data: { myObject: MyConstants.OPTION_ONE }, children: [ {
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'documents',
data: { myObject: MyConstants.OPTION_ONE },
children: [
{
path: ':ID_DOC',
children: [
{ path: 'edit', component: EditDocumentComponent },
{ path: '', component: DocumentDetailsComponent },
]
},
{ path: 'add', component: AddDocumentComponent },
{ path: '', component: DocumentsListComponent }
]
}
])
],
exports: [
RouterModule
]
})
export class DocumentsManagementRoutingModule {
}
如您所见,我使用data
属性将一些数据传递到“文档”中的每个路径,因此我可以从路由路径中声明的任何组件获取数据:
例如,以下是如何在文档详细信息组件中获取数据:
export class DocumentDetailsComponent implements OnDestroy {
private obsData: Subscription;
private option: any;
constructor(private route: ActivatedRoute) {
this.obsData = this.route.data.subscribe(data => {
this.option = data['myObject'];
});
}
ngOnDestroy(): void {
this.obsData.unsubscribe();
}
}
现在,我更改了整个应用程序的路由结构,并使用loadChildren
属性从其他模块调用上述模块。我以同样的方式传递数据:
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'users',
loadChildren: 'app/documents/documents.module#DocumentsModule',
data: { myObject: MyConstants.OPTION_ONE }},
{
path: ':ID_USER',
children: [
{ path: 'edit', component: EditUserComponent },
{ path: '', component: UserDetailsComponent },
]
},
{ path: 'add', component: AddUserComponent },
{ path: '', component: UserListComponent }
])
],
exports: [
RouterModule
]
})
export class UsersManagementRoutingModule {
}
我对调用DocumentsManagementRoutingModule
的所有其他模块也做了同样的操作,将myObject
属性更改为MyConstants.OPTION\u TWO
,MyConstants.OPTION\u TWO
等等,根据我的需要
然后,由于我不知道调用延迟加载模块的模块及其相关路径,如何从调用方模块获取数据属性?为什么不使用服务在模块或任何组件之间共享数据。您可以在主模块提供程序中导入此服务,因此可以在所有其他模块(延迟加载模块)中使用并共享数据
该服务可以具有设置和获取值的功能,因此您可以在服务中使用这些功能来获取所需的数据我想我可以理解问题所在
问题
以下是提供的plunker@smartmouse的路由图
- home
- shop
- contact
- map
- about
在home
路由配置上配置了一个data
对象。直接子路由可以访问此数据对象。问题是,非直接子map
希望访问数据
对象,但显然不能
我们可以知道@smartmouse希望进一步推动--嵌套的非直接子路由可以访问来自祖先的数据
为什么不能呢?
看看我改装的普朗克
您可以看到,我为contact
定义了一个额外的子组件DefaultComponent
。它显示它是routecontact
的直接和默认子级,可以解释为它也是上级routehome
的直接子级。因此,它可以访问数据
对象
解决方案
再看看我提供的弹夹
注意:我使用的Angular软件包是v4.3.0
方法#1——查询参数
我在home.component.ts中为contact
route定义了一些查询参数。你可以看看如何使用它
专业人士:
- 您可以跨任何级别的路由访问查询参数
- 适用于lazyload模块
缺点:
- 无法在路由配置中定义查询参数
但是您可以使用一些路由生命周期挂钩为目标祖先路由定义它们
方法2——服务
在应用程序的顶层定义一个数据共享服务,以单例模式运行。另外,使用一些util来防止它被启动两次。然后你可以把一些数据放进去,然后在任何地方检索
专业人士:
- 通过DI全球可见李>
- 适用于lazyload模块
缺点:
- 无法在路由配置中更新数据
- 您必须在其他地方定义数据。如果你不能控制它的来源,这可能是一个问题
方法#3——路线解析
有人可能会发现我还在plunker中定义了resolve
示例代码。这表明它与route config中的数据
具有相同的行为,只是它实际上用于动态数据检索
data属性用于将固定对象传递到激活的路由。它不会在应用程序的整个生命周期内更改。resolve属性用于动态数据
以@smartmouse的plunkr为例
我们在“主”路线配置中定义了数据
。我们可以在ContactModule
中为联系人的默认路由定义一个数据解析器,并代理从上级路由传递的数据。然后,其所有直接子路由都可以访问已解析的数据对象
专业人士:
- 适用于任何级别的嵌套管线
- 适用于lazyload模块
缺点:
- 您可能必须在其子路由希望访问该数据的每个父路由中声明resolve属性。这是一种肮脏的工作
目前还没有完美且通用的解决方案,通常使用角度。有人应该权衡利弊,选择合适的路由。您可以使用activatedRoute.pathFromRoot遍历父路由,并从最近的祖先那里获取可用的数据。类似的方法似乎奏效了:
ngOnInit(): void {
let idx = this.activatedRoute.pathFromRoot.length - 1;
while(this.sharedData == null && idx > 0){
this.sub = this.activatedRoute.pathFromRoot[idx].data.subscribe(subData => {
if(subData.id)
this.sharedData = subData;
console.log('shared data', this.sharedData);
});
idx--;
}
}
@NgModule({
进口:[
RouterModule.forChild([
{
路径:“用户”,
loadChildren:'app/documents/documents.module#DocumentsModule',
决心:{
数据:数据解析程序
}
{
])
],
出口:[
路由模块
]
})
导出类UsersManagementRoutingModule{
}
@可注射()
导出类DataResolution实现解析{
解决(){
返回此.serice.getData();
}
}
在我的情况下,可能会重复使用延迟加载模块mandatory@smartmouse有一行r.url.lastIndexOf(“/”))非法。在UsersManagementRoutingModule
的routes配置的第一级中,有双路径用于UsersManagementRoutingModule
如果我使用共享服务,则只有当您不通过直接url转到延迟加载模块时,它才会起作用。如果您转到属于延迟加载模块的页面,而不是通过pr发送数据的前一个模块
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'users',
loadChildren: 'app/documents/documents.module#DocumentsModule',
resolve : {
data: DataResolver
}
{
])
],
exports: [
RouterModule
]
})
export class UsersManagementRoutingModule {
}
@Injectable()
export class DataResolverimplements Resolve<Data> {
resolve() {
return this.serice.getData();
}
}