【问题标题】:Angular2 routing between sub-applications in modules模块中子应用程序之间的Angular2路由
【发布时间】:2016-10-26 17:03:40
【问题描述】:

我将 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 路由器的设计模式,允许导入其他模块的组件干净地引用自己模块的预配置路由,同时保持灵活的顶级路由定义?

【问题讨论】:

    标签: angular angular2-routing


    【解决方案1】:

    如果你想通过链接访问 M1 中的 M2Component,那么你应该使用 RouterModule 并且不要在 module1 中导入 module2。

    在module1内部使用

    RouterModule.forRoot([
        {
            path: 'module2',
            loadChildren: 'path-of-module2/module2.module#Module2Module'
        }
    ])
    

    在模块2中

    RouterModule.forChild([
        {
            path: '',
            component: Module2Component
        }
    ])
    

    现在您可以从路由“/module2”打开 Module2Component。

    【讨论】:

    • 确实,我忘记了我的帖子。从当前版本的 Angular (4.0.x) 开始,这是处理它的方法。去年 10 月我最初发帖时,Angular 是一个 2.0 版本,而我的样板方法似乎是唯一可行的前进道路。
    【解决方案2】:

    这是我所说的解决方案听起来很样板。它要求您使用一对不透明的令牌设置子应用程序模块:一个用于您的 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™(即,这样做)。然而,正如您所看到的,它也相当复杂只是允许模块中的实体路由到它们自己的模块中,尽管在没有硬编码路径的情况下实例化为另一个模块中的组件等。

    【讨论】:

      猜你喜欢
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      相关资源
      最近更新 更多