Angular 中返回 ModuleWithProviders 的参数化函数

parametrized function returning ModuleWithProviders in Angular

我有一个由多个组件组成的应用程序,每个组件都定义了自己的路线状态子集。根据集成这些组件的应用程序,它们(app)提供父状态,某些组件状态应放置在父状态下。即

组件状态:

[{
  name: 'component',
  url: '/component',
  component: ComponentRootComponent,
  abstract: true,
  default: '.list'
}, {
  name: 'component.list',
  url: '',
  component: ComponentListComponent
},...]

这是一些应用部分模块:

@NgModule({
  declarations: ...,
  imports: [
    UIRouterModule.forChild({ states: SECTION_STATES }),

    SomeComponentModule,
    UIRouterModule.forChild({
      states: RouterUtil.setParentState(SECTION_STATES[0].name, SOME_COMPONENT_STATES)
    })
  ]
})
export class AppSectionModule {}

setParentState() 函数只是遍历组件状态并在它们前面加上父状态名称前缀,因此它们低于特定的路由状态。

这一切都很棒,但与其为我的每个组件添加两个导入,我认为如果我为我的模块提供一个函数,允许我对每个组件有一个单一但可配置的导入会更好。

@NgModule({
  declarations: ...,
  imports: [
    UIRouterModule.forChild({ states: SECTION_STATES }),
    SomeComponentModule.importFor(SECTION_STATES[0].name)        
  ]
})
export class AppSectionModule {}

importFor 因此应该 return ModuleWithProviders 类型,它是我的原始组件模块的包装器,它还应该定义组件路由并将其放置在特定的父路由下:

export class SomeComponentModule {
  public static importFor(parentState: string): ModuleWithProviders {
    return {
      ngModule: SomeComponentModule,
      providers: [
        // what do I do here?
      ]
    };
  }
}

如何实现这样的功能?我不知道在这个功能中应该如何调用或提供UIRuterModule.forChild(...)?这是我要解决的主要问题。

通过使用 "hidden" 模块,您可以完成此操作。

第一个模块有一个 forRoot() 或者在你的例子中有一个 importFor() 其中有一个指向隐藏模块的 ngModule。

这个模块是在调用 importFor 时导入的调用。 然后导入原始模块并将其导出以使其显示为隐藏。

我发现这是制作可重用模块的好方法,我可以简单地将这些模块放入我的项目中,所有东西都配置了 reducer、effects、routes 和所有 :)

@NgModule({
  imports: [
    SharedModule,
  ],
  declarations: [
    ...SHARED_COMPONENTS,
  ],
  exports: [
    ...SHARED_COMPONENTS,
  ]
})
export class SecurityModule {

  // when the user imports SecurityModule.forRoot() in the app module what we really import is the RootSecurityModule
  // but it will also create the IsAuthenticated guard
  // it also imports all the feature stuff such as reducers, effects and routes

  // if we then later on need to access shared components from the SecurityModule we can import the module without the forRoot()
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: RootSecurityModule, 
      providers: [
        IsAuthenticatedGuard,
      ],
    };
  }
}

@NgModule({
  imports: [

    // import the above module so that we get all the shared declarations
    SecurityModule,

    // import the "include once" modules for security
    StoreModule.forFeature('security', securityReducer),
    EffectsModule.forFeature([
      SecurityEffects
    ]),
    SecurityRoutingModule,
  ],

  // we need to export the SecurityModule otherwise SecurityModule.forRoot() will not mean the same thing as SecurityModule
  exports: [
    SecurityModule,
  ]
})
export class RootSecurityModule {}

检查 UIRouterModule 实际做了什么,这似乎按预期工作:

export class SomeComponentModule {
  public static importBelowState(parentState: string): ModuleWithProviders {
    return {
      ngModule: SomeComponentModule,
      providers: UIRouterModule.forChild({ states: RouterUtil.setParentState(parentState, SOME_COMPONENT_STATES) }).providers
    };
  }
}

所以现在我可以在导入组件模块的同时配置其路由状态,如问题所示:

@NgModule({
  declarations: ...,
  imports: [
    UIRouterModule.forChild({ states: SECTION_STATES }),
    SomeComponentModule.importBelowState(SECTION_STATES[0].name)        
  ]
})
export class AppSectionModule {}