Angular2:多个模块中的一个模块实例

Posted

技术标签:

【中文标题】Angular2:多个模块中的一个模块实例【英文标题】:Angular2: One instance of module in multiple modules 【发布时间】:2017-05-05 18:23:14 【问题描述】:

让我们以ng2-translate 插件为例。

我有根AppModule,还有孩子TopPanelModulePagesModule


我为AppModule配置了ng2-translate

@NgModule(
  imports: [TranslateModule.forRoot(
    provide: TranslateLoader,
    useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'),
    deps: [Http]
  )],
  exports: []
)
export class AppModule 
  constructor(translateService: TranslateService)     
  


AppComponent 中,我为TranslateModule 设置语言和基本配置。

@Component(...)
export class AppComponent 
  constructor(translateService: TranslateService) 
    translateService.addLangs(["en", "fr"]);
    translateService.setDefaultLang('fr');

    const browserLang = 'fr';
    translateService.use(browserLang.match(/en|fr/) ? browserLang : 'en');    
  


然后我尝试在子模块组件中使用TranslateModule - TopPanelComponentPagesComponent。它不起作用。管道不存在错误,没有翻译等。


为了解决这个问题,我创建了一个单独的模块MyTranslateModule,在上面配置TranslateModule,并在我的PagesModuleTopPanelModule中使用这个模块。

@NgModule(
  imports: [TranslateModule.forRoot(
    provide: TranslateLoader,
    useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'),
    deps: [Http]
  )],
  exports: [TranslateModule]
)
export class MyTranslateModule 
  constructor(translateService: TranslateService) 
    translateService.addLangs(["en", "fr"]);
    translateService.setDefaultLang('fr');

    const browserLang = 'fr';
    translateService.use(browserLang.match(/en|fr/) ? browserLang : 'en');

    console.log('AdminTrModule: calling');
  

@NgModule(
  imports: [MyTranslateModule]
)
export class PagesModule



@NgModule(
  imports: [MyTranslateModule]
)
export class TopPanelModule



这是重要的部分。它有效!但我认为它创建了两个 TranslateModule 实例,因此,当我通过调用 TopComponent translateService.use('en') 更改翻译语言时,它会更改 TopPanelModule 中的语言,但不会更改 PagesModule 中的语言。

【问题讨论】:

你在使用延迟加载吗? @GünterZöchbauer,如果我知道的话,angular2 默认使用延迟加载。 不,当你在路由中使用loadChildren时会使用延迟加载。 这就是导致生成多个实例的原因。默认情况下,所有导入模块的所有提供程序都注册在应用程序根范围内,但延迟加载的模块有自己的根范围(这是应用程序根范围的子范围)。当来自延迟加载模块的组件或服务注入一些服务并且延迟加载模块让它从那里注册一个实例时,只有当延迟加载模块没有提供程序 DI 检查应用程序根范围时。所有请求相同依赖项的非延迟加载模块都从应用根目录获取一个 检查angular.io/docs/ts/latest/guide/ngmodule.html。我从来没有深入探讨过如何确保延迟加载模块的服务在应用程序根范围内注册,但我想这是可能的。还要检查底部的链接(angular.io/docs/ts/latest/cookbook/ngmodule-faq.html) 【参考方案1】:

你需要在模块'MyTranslateModule'中定义一个forRoot函数

export class MyTranslateModule 

static forRoot(): ModuleWithProviders 
    return 
      ngModule: MyTranslateModule ,
      providers: [TranslateService,TRANSLATION_PROVIDERS]
    ;
  


然后在 appModule 中导入 MyTranslateModule 如下

@NgModule(
  bootstrap: [App],
  declarations: [
    App
  ],
  imports: [ // import Angular's modules
    BrowserModule,
    MyTranslateModule.forRoot(),
    PagesModule,
    TopPanelModule
  ],
  providers: [ // expose our Services and Providers into Angular's dependency ]
)

在这种情况下,翻译服务将被创建为单例“应用程序中的一个实例”

【讨论】:

以上是关于Angular2:多个模块中的一个模块实例的主要内容,如果未能解决你的问题,请参考以下文章

如何在angular2中的每条路线更改上调用一个函数

Angular 2 - 多个模块中的管道重用 - 未找到错误或重复定义

AngularJs中的模块定义,一个页面加载多个ng-app

没有导出的成员/节点模块

Angular2 - 多个模块的共享布局

Angular 2 为多个模块定义数据模型