【问题标题】:Angular2: One instance of module in multiple modulesAngular2:多个模块中的一个模块实例
【发布时间】: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

标签: angular typescript module components


【解决方案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 ]
})

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 2021-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多