动态

详情 返回 返回

關於 Angular 應用 Components 和 Directives 的實例化問題 - 动态 详情

同 Angular Module 不同,Angular Components 和 Directives 要實例化多次,每個出現在 HTML template 中的 markup 都會對應一次實例化。

此外,這些項的作用域也限定在它們被導入的 NgModule中,以防止兩個組件使用相同的選擇器時發生命名衝突。由於依賴注入(DI)行為的這種差異,需要區分一個包含組件和指令的 NgModule 和一個包含組件、指令和 providers 的 ModuleWithProviders 是很有幫助的,這正是forRoot()方法進行區分的地方。

下面是 SAP Spartacus 關於 forRoot 方法的一個例子:

export class SiteContextModule {
  static forRoot(): ModuleWithProviders<SiteContextModule> {
    return {
      ngModule: SiteContextModule,
      providers: [
        provideDefaultConfigFactory(defaultSiteContextConfigFactory),
        contextServiceMapProvider,
        ...contextServiceProviders,
        ...siteContextParamsProviders,
        provideConfigValidator(baseSiteConfigValidator),
        {
          provide: CONFIG_INITIALIZER,
          useFactory: initSiteContextConfig,
          deps: [SiteContextConfigInitializer, SiteContextConfig],
          multi: true,
        },
        ...contextInitializerProviders,
      ],
    };
  }
}

然而,依賴注入並不總是這麼簡單。有些時候,應用程序的所有ngmodule在引導過程中都不可用。延遲加載就是這樣一個例子。當在路由過程中惰性加載NgModule時,在惰性加載的NgModule中註冊的提供商及其子模塊在引導過程中不可用,Angular 那時無法註冊它們。因此,它們只有在加載路由時才會被添加為提供商,而且它們的作用域會從惰性加載的NgModule及其子模塊開始注入。如果有多個惰性加載 NgModule 試圖註冊相同的提供商,那麼 NgModule 樹中的每個節點最終都會擁有不同的實例。通過在根目錄下導入提供商,它有助於確保所有惰性加載的 ngmodule 都能獲得該提供商的同一個實例,這也是forRoot() 被命名為該實例的原因。

總結

何時使用 Module 的 forRoot 方法?簡言之,當一個庫的 dependency 需要某個 module 時,就調用該 module 的 forRoot 方法,達到全局(globally)導入 providers 的目的。

在其他 ngmodule中,必要時使用 import 的非根形式來導入組件和指令。

當一個特性 NgModule 導出的組件和指令需要共享相同的自定義提供商實例時,請考慮用forRoot()方法在根NgModule中註冊這些提供商。這有助於確保所有子ngmodule都能訪問相同的提供商實例,而不需要使用者顯式地處理提供商註冊。

user avatar daishuyunshuzhanqianduan 头像 matrixorigin 头像
点赞 2 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.