簡體   English   中英

Angular 2如何為延遲加載的模塊提供單例服務

[英]Angular 2 How to make singleton service available to lazy loaded modules

根據我對Angular 2 rc5理解,要從另一個模塊(不是AppModule )提供服務作為單個模塊提供給每個組件,即使是那些延遲加載的模塊,我們也不會將該服務包含在該其他模塊的providers數組中。 我們用RouterModule.forRoot()導出它, RouterModule.forRoot()AppModule導入結果

根據文件

SharedModule應僅在根AppModule導入時提供UserService。 SharedModule.forRoot方法幫助我們應對這一挑戰...... SharedModule沒有providers ......當我們將SharedModule添加到AppModule的導入時,我們調用forRoot。 這樣,AppModule獲得導出的類,SharedModule同時提供單例UserService提供程序

我真的很掙扎如何為延遲加載的路由提供第三方服務(我的AppModuleimports數組中的模塊使用的服務)。 我無法控制這個第三方模塊,因此我不能只從該模塊的NgModule.providers數組中刪除該服務,並將其放在RouterModule.forRoot()就像我使用其中一個服務一樣。

具體服務是MdIconRegistry ,它是Angular Material 2 alpha 7-3MdIconModuleproviders 此服務用於注冊svg圖標,然后可以使用<md-icon svgIcon='iconName'>標記在頁面上顯示這些<md-icon svgIcon='iconName'> 所以:

  • 我進口MdIconModule在我的根AppModule
  • 我使用有問題的服務在我的AppComponent注冊svg圖標

該圖標可見並且運行良好,但僅限於啟動時加載的模塊。 延遲加載的模塊無法看到這些圖標,因此我懷疑Angular注入器沒有注入MdIconRegistry服務的相同實例。

tl; dr:我怎樣才能從第三方模塊中將服務作為我的延遲加載組件的單例?

這是一個演示問題的plunker (用typescript編碼)。

PS:這引起了github上 MdIconModule開發人員的注意

I do not think it has anything to do with the component being lazy-loaded.

LazyLoadedComponent不是AppModule的一部分 - 它是LazyModule的一部分。 根據文檔,組件只能是一個模塊的一部分。 如果您嘗試將LazyLoadedComponent添加到AppModule,則會出現相應的錯誤。 所以LazyLoadedComponent甚至根本沒有看到MdIconModule。 您可以通過查看調試器中的模板輸出來確認這一點 - 它保持不變。

<md-icon svgIcon="play"></md-icon>

解決方案似乎是將MdIconModule添加到LazyModule,雖然僅此一項不能解決問題,但它確實會在輸出中添加錯誤。

檢索圖標時出錯:錯誤:無法找到名稱為“:play”的圖標

現在模板輸出看起來像這樣,所以我們知道它正在加載。

<md-icon role="img" svgicon="play" ng-reflect-svg-icon="play" aria-label="play"></md-icon>

我從LazyLoadedComponent添加了對addSvgIconSet的調用,並且它使它工作......所以這證明每個組件有一個MdIconRegistry服務的實例 - 不是你想要的,但可能指向正確的方向。

這是新的插件 - http://plnkr.co/edit/YDyJYu?p=preview

經過進一步審核后,我在文檔中發現了這一點:

為什么延遲加載的模塊中提供的服務僅對該模塊可見?

與啟動時加載的模塊的提供者不同,延遲加載的模塊的提供者是模塊范圍的。

最后更新! 這是答案。 沒有為延遲加載的組件正確設置MdIconModule ...但我們可以輕松創建我們自己的模塊,該模塊已正確設置並使用它。

import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';

import { MdIcon } from '@angular2-material/icon';
import { MdIconRegistry } from '@angular2-material/icon';

@NgModule({
  imports: [HttpModule],
  exports: [MdIcon],
  declarations: [MdIcon]
})
export class MdIconModuleWithProviders {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: MdIconModuleWithProviders,
      providers: [ MdIconRegistry ]
    };
  }
}

Plunk更新並完全正常工作。 (對不起,更新了同一個) - > http://plnkr.co/edit/YDyJYu?p=preview

有人可能會提交拉取請求,以便Angular Material導出兩種樣式的模塊。

Angular 6的新功能是將提供程序注冊為單例的新方法。 在服務的@Injectable()裝飾器中,使用providedIn屬性。 將其值設置為“root”。 然后你不需要將它添加到根模塊的提供者列表中,或者在這種情況下你也可以將它設置為你的MdIconModuleWithProviders模塊,如下所示:

@Injectable({
  providedIn: MdIconModuleWithProviders // or 'root' for singleton
})
export class MdIconRegistry {
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM