21

我的 Angular 应用程序模块有以下路由路径:

@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属性将一些数据传递给“文档”中的每个路径,因此我可以从路由路径中声明的任何组件中获取它:

例如,这是我获取数据的方式DocumentDetailsComponent

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_TWOMyConstants.OPTION_THREE

那么,由于我不知道调用我的延迟加载模块的模块及其相关路径,如何data从调用者模块获取属性?

4

5 回答 5

11

我想我可能明白这个问题在问什么。


问题

这是提供的 plunker @smartmouse 的路由图。

- home
  - shop
  - contact
    - map
  - about

在路由配置上配置了一个data对象。home直接子路由可以访问此数据对象。问题是,非直接孩子map想要访问该data对象,但显然它不能。

我们可以知道@smartmouse 想要进一步推动——嵌套的非直接子路由可以访问来自祖先的数据

为什么不能?

请参阅我修改过的 plunker。https://plnkr.co/edit/FA7mGmspUXHhU8YvgDpT

你可以看到我DefaultComponentcontact. 说明它是路由的直接默认子路由contact,可以理解为也是上级路由的直接子路由home。因此,它可以访问该data对象。

解决方案

再看看我提供的plunker。

注意:我使用的 Angular 包是 v4.3.0

方法#1——查询参数

home.component.ts我在contact路由中定义了一些查询参数。你可以看看如何使用它。

优点

  • 您可以跨任何级别的路由访问查询参数。
  • 与延迟加载模块配合良好

缺点

  • 您不能在路由配置中定义查询参数。

    但是您可以使用一些路由生命周期挂钩来为目标祖先路由定义它们

方法#2——服务

在作为单例模式运行的应用程序的顶层定义数据共享服务。另外,使用一些工具来防止它被启动两次。然后,您可以将一些数据放入其中,并在任何地方检索它。

优点

  • 通过 DI 全局可见;
  • 与延迟加载模块配合良好

缺点

  • 您无法更新路由配置中的数据。
  • 您必须在其他地方定义数据。如果你不能控制它的来源,它可能是一个问题。

方法#3——路由解析

有人可能会发现我还在resolveplunker 中定义了示例代码。这是为了表明它具有与data路由配置相同的行为,除了它实际上是用于动态数据检索。

https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab#5400
data 属性用于将固定对象传递给激活的路由。它在应用程序的整个生命周期内都不会改变。resolve 属性用于动态数据。

以@smartmouse 的 plunkr 为例。

我们已经data在“home”路由配置中定义了。我们可以在ContactModule联系人的默认路由中定义一个数据解析器,代理上级路由传递过来的数据。然后它的所有直接子路由都可以访问解析的数据对象。

优点

  • 适用于任何级别的嵌套路由
  • 与延迟加载模块配合良好

缺点

  • 您可能必须在其子路由想要访问该数据的每个父路由中声明该解析属性。这是一种肮脏的工作。

目前还没有完美且通用的解决方案,可以普遍使用 Angular。有人应该权衡利弊并选择合适的。

于 2017-07-19T12:42:34.783 回答
9

您可以使用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--;
    }
  }

https://plnkr.co/edit/K5Rb1ZvTvSQNM6tOLeFp

于 2017-07-20T05:22:08.757 回答
1
@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();
  }
}
于 2017-07-20T05:44:49.410 回答
0

为什么不使用服务在模块或任何组件之间共享数据。您可以在主模块提供程序处导入此服务,因此可以在所有其他模块(延迟加载模块)中使用并共享数据。

该服务可以具有设置和获取值的功能,因此您可以在服务中使用这些功能来获取所需的数据

于 2017-07-13T12:40:18.920 回答
0

如果您现在在这里结束,请查看路由器配置选项paramsInheritanceStrategy。它允许您细化“路由器如何合并参数、数据和从父路由到子路由的解析数据”。我有一些未发送到延迟加载模块的已解析数据,将参数设置为“始终”为我解决了这个问题。

于 2021-09-24T17:43:16.443 回答