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

Angular2 Bootstrap Providers vs provides array in component

首先,我们可能有一个不寻常的 angular2 架构,其中我们 bootstrap 在单个页面上有多个组件(小部件),而不是处理所有事情的单个应用程序组件。

我的第一个问题是,下面两个实现是否相同,据我了解,它们是(如果理解有误,请指正):

 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 的子组件共享。如果一样,有没有什么preferred/recommended方法?

现在第二个问题是,如何在不在同一 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}))

Angular DI 创建注入器层次结构,其中根由 bootstrap() 创建,提供者传递给 bootstrap().
默认情况下 Angular 提供的所有内容也会添加到此注入器(如 PLATFORM_PIPESPLATFORM_DIRECTIVES、...)

然后从根组件开始,使用根组件提供的提供程序创建子注入器。对于根组件的每个子组件和指令,都会创建子注入器,一直到叶组件和指令。

因此,注入器层次结构类似于您的组件和指令层次结构。

当现在组件需要依赖项(构造函数参数)时,DI 会在它的注入器提供程序上查找它。如果找不到它,它会检查父注入器,然后继续检查由 bootstrap().

创建的根注入器

这应该很清楚 bootstrap() 的提供者或根组件的提供者导致完全相同的行为。

你在两个单独引导的组件之间共享服务的方法对我来说似乎很好,除了 AFAIK 它应该是 useValue 而不是 instance

bootstrap(SomeComponent1, provide(FooService, {useValue: foo}))

另见

如此处所述,如果您使用共享服务中的可观察对象发出值,则该值会在发件人区域中发出,并且其他应用程序中的订阅者会在发件人区域中被调用。确保使用 zone.run

constructor(sharedService:FooService, zone:NgZone) {
  sharedService.someObservable.subscribe(value => {
    zone.run(() => {
      this.data = value;
      this.router.navigate...
      ...
    });
  });
}

仅供参考,如果有人偶然发现此 post 并且在没有中央应用程序组件时共享实例也有一些问题。

我的最终实现是这样的,它是一个需要注入服务本身的服务和一个简单服务的示例:

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);
}