Gibt es kein Äquivalent zu $scope.emit()
oder $scope.broadcast()
in Angular?
Ich kenne die EventEmitter
Funktionalität, aber soweit ich weiß , wird nur ein Ereignis an das übergeordnete HTML-Element ausgegeben.
Was ist, wenn ich zwischen fx kommunizieren muss? Geschwister oder zwischen einer Komponente in der Wurzel des DOM und einem Element, das mehrere Ebenen tief verschachtelt ist?
Antworten:
Es gibt kein Äquivalent zu
$scope.emit()
oder$scope.broadcast()
von AngularJS. EventEmitter innerhalb einer Komponente kommt nahe, aber wie Sie bereits erwähnt haben, gibt es nur ein Ereignis an die unmittelbare übergeordnete Komponente aus.In Angular gibt es andere Alternativen, die ich unten erklären möchte.
Mit @Input () -Bindungen kann das Anwendungsmodell in einem gerichteten Objektdiagramm (Wurzel zu Blättern) verbunden werden. Das Standardverhalten der Änderungsdetektorstrategie einer Komponente besteht darin, alle Änderungen an einem Anwendungsmodell für alle Bindungen einer verbundenen Komponente weiterzugeben.
Nebenbei: Es gibt zwei Arten von Modellen: Ansichtsmodelle und Anwendungsmodelle. Ein Anwendungsmodell ist über @ Input () -Bindungen verbunden. Ein Ansichtsmodell ist nur eine Komponenteneigenschaft (nicht mit @Input () dekoriert), die in der Vorlage der Komponente gebunden ist.
So beantworten Sie Ihre Fragen:
Was ist, wenn ich zwischen Geschwisterkomponenten kommunizieren muss?
Gemeinsames Anwendungsmodell : Geschwister können über ein gemeinsames Anwendungsmodell kommunizieren (genau wie Winkel 1). Wenn beispielsweise ein Geschwister eine Änderung an einem Modell vornimmt, wird das andere Geschwister, das Bindungen an dasselbe Modell aufweist, automatisch aktualisiert.
Komponentenereignisse : Untergeordnete Komponenten können mithilfe von @ Output () - Bindungen ein Ereignis an die übergeordnete Komponente senden. Die übergeordnete Komponente kann das Ereignis verarbeiten und das Anwendungsmodell oder das eigene Ansichtsmodell bearbeiten. Änderungen am Anwendungsmodell werden automatisch an alle Komponenten weitergegeben, die direkt oder indirekt an dasselbe Modell gebunden sind.
Serviceereignisse : Komponenten können Serviceereignisse abonnieren. Beispielsweise können zwei Geschwisterkomponenten dasselbe Serviceereignis abonnieren und darauf reagieren, indem sie ihre jeweiligen Modelle ändern. Mehr dazu weiter unten.
Wie kann ich zwischen einer Root-Komponente und einer Komponente kommunizieren, die mehrere Ebenen tief verschachtelt ist?
$scope.broadcast()
Angular 1. Im nächsten Abschnitt wird diese Idee ausführlicher beschrieben.Beispiel eines beobachtbaren Dienstes, der Dienstereignisse verwendet, um Änderungen zu verbreiten
Hier ist ein Beispiel für einen beobachtbaren Dienst, der Dienstereignisse verwendet, um Änderungen weiterzugeben. Wenn ein TodoItem hinzugefügt wird, gibt der Dienst ein Ereignis aus, das seine Komponententeilnehmer benachrichtigt.
So würde eine Root-Komponente das Ereignis abonnieren:
Eine untergeordnete Komponente, die mehrere Ebenen tief verschachtelt ist, würde das Ereignis auf dieselbe Weise abonnieren:
Hier ist die Komponente, die den Dienst aufruft, um das Ereignis auszulösen (sie kann sich an einer beliebigen Stelle im Komponentenbaum befinden):
Referenz: Änderungserkennung im Winkel
quelle
itemAdded$
. Ist das eine RxJS-Konvention oder so? Woher kommt das?street
Eigenschaft des App-Modells ändert. Da Angular 2 jedoch die Änderungserkennung durch Identität / Referenz implementiert, werden keine Änderungen weitergegeben (onChanges
wird nicht aufgerufen), da sich die Referenz des App-Modells nicht geändert hat ( Fortsetzung ...)Der folgende Code als Beispiel für einen Ersatz für $ scope.emit () oder $ scope.broadcast () in Angular 2 unter Verwendung eines gemeinsam genutzten Dienstes zur Behandlung von Ereignissen.
Anwendungsbeispiel:
Übertragung:
Hörer:
Es kann mehrere Argumente unterstützen:
quelle
off(name, listener) { this.listeners[name] = this.listeners[name].filter(x => x != listener); }
Ich verwende einen Nachrichtendienst, der ein rxjs
Subject
(TypeScript) umschließt.Plunker-Beispiel: Nachrichtendienst
Komponenten können Ereignisse abonnieren und senden (Absender):
(Empfänger)
Die
subscribe
MethodeMessageService
gibt ein rxjs-Subscription
Objekt zurück, das wie folgt abgemeldet werden kann:Siehe auch diese Antwort: https://stackoverflow.com/a/36782616/1861779
Plunker-Beispiel: Nachrichtendienst
quelle
Property 'filter' does not exist on type 'Subject<EventMessage>'.
this.handler.pipe(filter(...))
. Siehe Vermietbare Betreiber .return this.handler.pipe( filter(message => message.type === type), map(message => message.payload) ).subscribe(callback);
Verwenden Sie EventEmitter nicht für Ihre Servicekommunikation.
Sie sollten einen der Observable-Typen verwenden. Ich persönlich mag BehaviorSubject.
Einfaches Beispiel:
Sie können den Anfangszustand übergeben, hier übergebe ich null
Wenn Sie den Betreff aktualisieren möchten
Beobachten Sie alle Dienste oder Komponenten und handeln Sie, wenn neue Updates eingehen.
Hier finden Sie weitere Informationen. .
quelle
Mit
EventEmitter oderObservables können Sie einen Eventbus-Dienst erstellen, den Sie bei DI registrieren. Jede Komponente, die teilnehmen möchte, fordert lediglich den Dienst als Konstruktorparameter an und sendet und / oder abonniert Ereignisse.Siehe auch
quelle
Meine Lieblingsmethode ist die Verwendung von Verhaltensthemen oder Ereignisemittern (fast gleich) in meinem Dienst, um alle meine Unterkomponenten zu steuern.
Führen Sie mithilfe von Angular Cli ng gs aus, um einen neuen Dienst zu erstellen, und verwenden Sie dann ein BehaviorSubject oder EventEmitter
Wenn Sie dies tun, wird jede Komponente, die Ihren Dienst als Anbieter verwendet, über die Änderung informiert. Abonnieren Sie das Ergebnis einfach wie bei eventEmitter;)
quelle
Ich habe hier ein Pub-Sub-Beispiel erstellt:
http://www.syntaxsuccess.com/viewarticle/pub-sub-in-angular-2.0
Die Idee ist, RxJs Subjects zu verwenden, um einen Observer und und Observables als generische Lösung für das Ausgeben und Abonnieren von benutzerdefinierten Ereignissen zu verkabeln. In meinem Beispiel verwende ich ein Kundenobjekt für Demozwecke
Hier ist auch eine Live-Demo: http://www.syntaxsuccess.com/angular-2-samples/#/demo/pub-sub
quelle
Dies ist meine Version:
verwenden:
}}
emittieren:
quelle
Wir haben eine beobachtbare ngModelChange-Direktive implementiert, die alle Modelländerungen über einen Ereignisemitter sendet, den Sie in Ihrer eigenen Komponente instanziieren. Sie müssen lediglich Ihren Event-Emitter an die Direktive binden.
Siehe: https://github.com/atomicbits/angular2-modelchangeobservable
Binden Sie in HTML Ihren Ereignisemitter (in diesem Beispiel countryChanged):
Führen Sie in Ihrer Typoskriptkomponente einige asynchrone Vorgänge für den EventEmitter aus:
quelle
Serviceereignisse: Komponenten können Serviceereignisse abonnieren. Beispielsweise können zwei Geschwisterkomponenten dasselbe Serviceereignis abonnieren und darauf reagieren, indem sie ihre jeweiligen Modelle ändern. Mehr dazu weiter unten.
Stellen Sie jedoch sicher, dass Sie sich bei der Zerstörung der übergeordneten Komponente abmelden.
quelle