[英]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
提供程序
我真的很掙扎如何為延遲加載的路由提供第三方服務(我的AppModule
的imports
數組中的模塊使用的服務)。 我無法控制這個第三方模塊,因此我不能只從該模塊的NgModule.providers
數組中刪除該服務,並將其放在RouterModule.forRoot()
就像我使用其中一個服務一樣。
具體服務是MdIconRegistry
,它是Angular Material 2 alpha 7-3
的MdIconModule
的providers
。 此服務用於注冊svg圖標,然后可以使用<md-icon svgIcon='iconName'>
標記在頁面上顯示這些<md-icon svgIcon='iconName'>
。 所以:
MdIconModule
在我的根AppModule
AppComponent
注冊svg圖標 該圖標可見並且運行良好,但僅限於啟動時加載的模塊。 延遲加載的模塊無法看到這些圖標,因此我懷疑Angular注入器沒有注入MdIconRegistry
服務的相同實例。
tl; dr:我怎樣才能從第三方模塊中將服務作為我的延遲加載組件的單例?
這是一個演示問題的plunker (用typescript
編碼)。
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.