首先,我们可能有一个不寻常的angular2架构,我们在一个页面上引导多个组件(小部件),而不是一个处理所有内容的应用程序组件。
我的第一个问题是,根据我的理解,以下两个实现是否相同,它们是(如果我误解了某些内容,请纠正我):
bootstrap(SomeComponent, [HTTP_PROVIDER, FooService, ServiceNeededByFoo])
这会初始化SomeComponent并将三个服务的提供者放在那里。这样SomeComponent可以在自己的构造函数中解析FooService,并且FooService可以解析ServiceNeededByFoo,因为它在SomeComponent(父元素)中查找它。
如果我定义
providers: [HTTP_PROVIDER, FooService, ServiceNeededByFoo]
在SomeComponent中,我可以像这样初始化它:
bootstrap(SomeComponent)
因此,根据我的理解,这些应该完全相同,在SomeComponent级别创建FooService和ServiceNeededByFoo的新实例,并与SomeComponent的所有子级共享,这些子级也需要FooService。如果相同,是否有任何首选/推荐方式?
现在的第二个问题是,如何在不属于同一DI层次结构的组件之间共享单个FooService实例:
bootstrap(SomeComponent1, FooService)
bootstrap(SomeComponent2, FooService)
其中FooService应该是同一个实例。类似的东西:
var foo = new FooService();
foo.expensiveInit();
bootstrap(SomeComponent1, provide(FooService, {instance: foo}))
bootstrap(SomeComponent2, provide(FooService, {instance: foo}))
答案 0 :(得分:2)
Angular DI创建了一个注入器层次结构,其中根由bootstrap()
创建,提供者传递给bootstrap()
。
Angular默认提供的所有内容也会添加到此注入器中(例如PLATFORM_PIPES
,PLATFORM_DIRECTIVES
,...)
然后从根组件开始,使用根组件提供的提供程序创建子注入器。对于根组件的每个子组件和指令,将创建子注入器,直到叶组件和指令。
因此,进样器层次结构类似于组件和指令层次结构。
现在一个组件需要一个依赖项(构造函数参数),DI在它的注入器提供程序上查找它。如果找不到它,它会检查父注射器,并继续执行由bootstrap()
创建的根注射器。
这应该很清楚bootstrap()
的提供者或根组件的提供者导致完全相同的行为。
您在两个单独引导的组件之间共享服务的方法对我来说似乎不错,但AFAIK应该是useValue
而不是instance
bootstrap(SomeComponent1, provide(FooService, {useValue: foo}))
另见
如上所述,如果使用共享服务中的observable发出值,则会在发件人区域中发出值,而在发件人区域中调用其他应用程序中的订阅者。确保使用zone.run
constructor(sharedService:FooService, zone:NgZone) {
sharedService.someObservable.subscribe(value => {
zone.run(() => {
this.data = value;
this.router.navigate...
...
});
});
}
答案 1 :(得分:1)
仅供参考,如果有人偶然发现此帖子,并且在没有中央应用程序组件时也会遇到共享实例的问题。
我的最终实现看起来像这样,它是一个需要注入服务本身和简单服务的服务的例子:
var cs = new ConfigurationService();
var injector = ReflectiveInjector.resolveAndCreate([TranslateService, provide(TranslateLoader, {useClass: JsonLoader}), HTTP_PROVIDERS]);
var ts = injector.get(TranslateService);
ts.setDefaultLang('en');
ts.use(cs.getLanguage());
var defaultProviders = [provide(TranslateService, {useValue: ts}), provide(ConfigurationService, {useValue: cs})];
if ($('notification-widget').length > 0) {
bootstrap(NotificationWidgetComponent, defaultProviders);
}
if ($('livesearch-widget').length > 0){
bootstrap(LivesearchWidgetComponent, defaultProviders);
}