2016-06-07 6 views
2

Zunächst einmal haben wir wahrscheinlich eine ungewöhnliche angular2 Architektur, wo wir mehrere Komponenten (Widgets) auf einer einzigen Seite Bootstrap und nicht eine einzige App-Komponente, die alles behandelt.Angular2 Bootstrap Provider vs bietet Array in Komponente

Meine erste Frage ist, ob die folgenden zwei Implementierungen gleich sind, von dem, was ich verstanden, sie sind (bitte korrigieren Sie mich, wenn ich etwas falsch verstanden):

bootstrap(SomeComponent, [HTTP_PROVIDER, FooService, ServiceNeededByFoo]) 

Dies initialisiert SomeComponent und stellt die Anbieter für die drei Dienste dort. Auf diese Weise kann SomeComponent FooService in seinem eigenen Konstruktor auflösen, und FooService kann ServiceNeededByFoo auflösen, da es in SomeComponent (dem übergeordneten) nachgeschlagen wird.

Wenn ich

providers: [HTTP_PROVIDER, FooService, ServiceNeededByFoo] 

innerhalb SomeComponent definieren, kann ich es wie so initialisieren:

bootstrap(SomeComponent) 

Also von dem, was ich verstehe diese völlig gleich sein sollte, eine neue Instanz für FooService und ServiceNeededByFoo auf der Ebene von SomeComponent wird erstellt und für alle untergeordneten Elemente von SomeComponent freigegeben, die ebenfalls FooService benötigen. Wenn es das gleiche ist, gibt es einen bevorzugten/empfohlenen Weg?

Die zweite Frage ist nun, wie kann ich eine einzelne Instanz FooService über Komponenten teilen, die nicht in der gleichen DI Hierarchie sind:

bootstrap(SomeComponent1, FooService) 
bootstrap(SomeComponent2, FooService) 

wo die FooService sollte die gleiche Instanz sein. Etwas wie:

var foo = new FooService(); 
foo.expensiveInit(); 
bootstrap(SomeComponent1, provide(FooService, {instance: foo})) 
bootstrap(SomeComponent2, provide(FooService, {instance: foo})) 

Antwort

1

Gerade als Referenz, wenn jemand auf diesen Beitrag stolpert und hat auch einige Probleme mit gemeinsamen Fälle, in denen es keine zentrale App Komponente ist.

Meine endgültige Umsetzung wie folgt aussieht, dann ist es ein Beispiel mit einem Service, injiziert Dienste selbst benötigt und einen einfachen Service:

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

Die bereitgestellten Methoden und die Provider-Klasse werden nun ab rc3 entzogen, ich habe den Ersatz noch nicht gefunden, da die Kommentare im Code einfach "TODO: improved docs" sagen – Tom

2

Angular DI erzeugt eine Hierarchie von Injektoren, wo die Wurzel von bootstrap() und die Anbieter weitergegeben bootstrap() erstellt wird.
Alle Sachen von Angular standardmäßig zur Verfügung gestellt und zu diesem Injektor hinzugefügt werden (wie PLATFORM_PIPES, PLATFORM_DIRECTIVES, ...)

Dann aus dem Stammkomponente ein Kind beginnt Injektor mit den Anbietern auf der Stammkomponente bereitgestellt erstellt. Für jede untergeordnete Komponente und Anweisung der Stammkomponente werden untergeordnete Injektoren erstellt, bis hin zu den Blattkomponenten und Anweisungen.

Die Injektorhierarchie ähnelt daher Ihrer Komponenten- und Direktivitätshierarchie.

Wenn jetzt eine Komponente eine Abhängigkeit benötigt (Konstruktorparameter), sucht DI die Injektoren-Provider. Wenn es nicht gefunden werden kann, prüft es die Eltern-Injektoren, und das geht bis zum Root-Injektor, der von bootstrap() erstellt wurde.

Dies sollte es ziemlich klar machen, dass Anbieter bei bootstrap() oder Anbieter bei Root-Komponente in ganz das gleiche Verhalten führen.

Ihr Ansatz einen Dienst zwischen zwei individuell Bootstrap-Komponenten zu teilen mir scheint in Ordnung, außer dass AFAIK es useValue statt instance

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

Siehe auch

sein sollte

Wie dort erwähnt, wenn Sie Werte mit einer Observabl ausgeben e Im Shared Service wird der Wert in der Absenderzone und die Teilnehmer in der anderen Anwendung in der Absenderzone aufgerufen. Stellen Sie sicher, Sie verwenden zone.run

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

Vielen Dank für die ausführliche Erklärung! Vor allem das Beispiel am Ende. – Tom