JavaScript - Ein Ereignis über einen Service in Angular auslösen
Was ist der richtige Weg, ein Ereignis über einen Service auszulösen. Ich habe gelesen, dass das Deklarieren des EventEmitter im Service nicht geeignet ist.
Ich möchte Folgendes erreichen.
Ich habe 2 Komponenten innerhalb der Root-Komponente. Wenn ich auf die erste Komponente klicke, möchte ich in der zweiten Komponente wissen, dass die erste Komponente angeklickt wurde.
Antwort #1
Es gibt vier mögliche Szenarien, in denen Sie Ihre Daten teilen können, aber es hängt von Ihren Anforderungen ab.
Elternteil an Kind: Daten über Eingabe teilen
Kind zu Elternteil: Daten über ViewChild teilen
Kind an Elternteil: Datenübertragung via Output() und EventEmitter
Unabhängige Komponenten: Daten mit einem Dienst teilen
Beim Übergeben von Daten zwischen Komponenten, die keine direkte Verbindung haben, wie Geschwister, Enkel usw., sollten Sie einen gemeinsamen Dienst verwenden. Wenn Sie Daten haben, die immer synchron sein sollten, finde ich das RxJS BehaviorSubject in dieser Situation sehr nützlich.
Sie können auch ein normales RxJS Subject verwenden, um Daten über den Service zu teilen, aber hier ist der Grund, warum ich ein BehaviorSubject bevorzuge.
Es wird bei jeder Subscription immer den aktuellen Wert zurückgeben - es ist nicht nötig, onNext aufzurufen. Es hat eine getValue()-Funktion, um den letzten Wert als Rohdaten zu extrahieren. Dies stellt sicher, dass die Komponente immer die neuesten Daten erhält. Im Service erstellen wir ein privates BehaviorSubject, das den aktuellen Wert der Nachricht hält. Wir definieren eine currentMessage-Variable, um diesen Datenstrom als Observable zu handhaben, das von den Komponenten verwendet werden wird. Schließlich erstellen wir eine Funktion, die next auf dem BehaviorSubject aufruft, um dessen Wert zu ändern.
Die Eltern-, Kinder- und Geschwisterkomponenten erhalten alle die gleiche Behandlung. Wir injizieren den DataService im Konstruktor, abonnieren dann das currentMessage-Observable und setzen seinen Wert gleich der message-Variablen.
Wenn wir nun eine Funktion in einem dieser Komponenten erstellen, die den Wert der Nachricht ändert, wird beim Ausführen dieser Funktion die neuen Daten automatisch an alle anderen Komponenten weitergegeben. Hier ist ein Codeausschnitt.
data.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
parent.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-parent',
template: `
{{message}}
`,
styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
second.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-sibling',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Sibling")
}
}
