[英]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.