Angular2 Bootstrap Providers vs在组件中提供数组

时间:2016-06-07 09:44:05

标签: angular angular2-services

首先,我们可能有一个不寻常的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}))

2 个答案:

答案 0 :(得分:2)

Angular DI创建了一个注入器层次结构,其中根由bootstrap()创建,提供者传递给bootstrap()
Angular默认提供的所有内容也会添加到此注入器中(例如PLATFORM_PIPESPLATFORM_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);
}