Как использовать.forRoot() в иерархии модулей функций

Может ли кто-нибудь объяснить мне, как я должен структурировать иерархию нескольких вложенных функциональных модулей с помощью вызовов.forRoot()?

Например, что если у меня есть такие модули:

- MainModule
- SharedModule
- FeatureModuleA
    - FeatureModuleA1
    - FeatureModuleA2
- FeatureModuleB

Все функциональные модули имеют статические функции.forRoot().

Как мне определить FeatureModuleA с каким-то образом "передать" функции.forRoot()?

@NgModule({ 
  imports: [
    //- I can use .forRoot() calls here but this module not the root module
    //- I don't need to import sub-modules here, FeatureA only a wrapper
    //FeatureModuleA1.forRoot(), //WRONG!
    //FeatureModuleA2.forRoot(), //WRONG!
  ],
  exports: [
    //I cannot use .forRoot() calls here
    FeatureModuleA1, 
    FeatureModuleA2 
  ]
})
class FeatureModuleA {
  static forRoot(): ModuleWithProviders {
    return {
      //At this point I can set any other class than FeatureModuleA for root
      //So lets create a FeatureRootModuleA class: see below!
      ngModule: FeatureModuleA //should be: FeatureRootModuleA 
    };
  }
}

Я могу создать другой класс для использования root, а затем установить его в функции forRoot () FeatureModuleA:

@NgModule({
  imports: [
    //Still don't need any sub module within this feature module
  ]
  exports: [
    //Still cannot use .forRoot() calls but still need to export them for root module too:
    FeatureModuleA1, 
    FeatureModuleA2 
  ]
})
class FeatureRootModuleA { }

Но как я могу "перевести" вызовы.forRoot() в этот специальный ModuleClass?

Как я вижу, мне нужно импортировать все подмодули непосредственно в мой корневой MainModule и вызывать.forRoot() для каждого там:

@NgModule({
  imports: [
    FeatureModuleA1.forRoot(),
    FeatureModuleA2.forRoot(),
    FeatureModuleA.forRoot(),
    SharedModule.forRoot()
  ]
})
class MainModule { }

Я прав? Перед тем, как ответить, посмотрите этот файл: https://github.com/angular/material2/blob/master/src/lib/module.ts

Насколько мне известно, этот репо поддерживается официальной угловой командой. Таким образом, они решают вышеупомянутое, просто импортируя все вызовы.forRoot() в специальном модуле MaterialRootModule. Я не очень понимаю, как это будет применяться для моего собственного корневого модуля? Что на самом деле означает root и .forRoot? Это относится к пакету, а не к реальному веб-проекту?

3 ответа

Решение

В общем-то forRoot используется для добавления приложений / одноэлементных сервисов.

@NgModule({
  providers: [ /* DONT ADD HERE */ ]
})
class SharedModule {
  static forRoot() {
    return {
      ngModule: SharedModule,
      providers: [ AuthService ]
    }
  }
}

Причина заключается в том, что если вы добавите AuthService к providers в @NgModuleвозможно создание нескольких, если вы импортируете SharedModule в другие модули.

Я не уверен на 100%, будет ли создан сервис, когда SharedModule импортируется в загруженный модуль, но объяснение, что упомянутые документы были в отношении лениво загруженных модулей. Когда вы лениво загружаете модуль, все провайдеры будут созданы.

По этой причине мы добавляем (по соглашению) forRoot метод для обозначения того, что метод должен вызываться только для модуля root (app), в то время как для другого модуля он должен быть просто импортирован нормально

@NgModule({
  imports: [SharedModule]
})
class FeatureModule {}

@NgModule({
  imports: [SharedModule.forRoot()]
})
class AppModule {}

Как forRoot предназначены только для предоставления одноразовых услуг, вы можете явно "повторно" предоставить их в SharedModule:

@NgModule({})
class SharedModule {
  static forRoot() {
    return {
      ngModule: SharedModule,
      providers: [
        AuthService,
        FeatureModuleA.forRoot().providers,
        FeatureModuleB.forRoot().providers,
      ],
    }
  }
}

Таким образом, все услуги будут предоставлены SharedModule сам (не соответствующим подмодулем), но кажется, что это не имеет значения. Может быть, кто-то может поспорить, хотя...

Обратите внимание, что FeatureModuleA может также "повторно" предоставлять синглтон-сервисы из своих подмодулей аналогичным образом.

Как упомянуто выше, важно загружать модули с отложенной загрузкой, поскольку совместно используемую службу можно использовать в модуле с отложенной загрузкой, но если эта служба уже использовалась и создавалась другим модулем, тогда будет два экземпляра, следовательно, потребуется шаблон синглтона., Отличным примером здесь является AuthService - вы не хотите, чтобы один экземпляр службы был с неаутентифицированным пользователем, в то время как у другого "тот же" пользователь прошел аутентификацию.

В Angular 6 появился новый способ регистрации провайдера в качестве синглтона. Внутри декоратора @Injectable() для сервиса используйте атрибут предусмотрен In. Установите его значение "root". Тогда вам не нужно будет добавлять его в список поставщиков корневого модуля, или в этом случае вы также можете установить его в свой SharedModule следующим образом:

@Injectable({
  providedIn: SharedModule // or 'root' for singleton
})
export class AuthService {
...
Другие вопросы по тегам