Nie ma odpowiednika $scope.emit()
ani $scope.broadcast()
z AngularJS. EventEmitter wewnątrz komponentu jest blisko, ale jak wspomniałeś, będzie emitował zdarzenie tylko do bezpośredniego komponentu nadrzędnego.
W Angular istnieją inne alternatywy, które spróbuję wyjaśnić poniżej.
Powiązania @Input () pozwalają na podłączenie modelu aplikacji do grafu z ukierunkowanym obiektem (root do liści). Domyślnym zachowaniem strategii detektora zmian w komponencie jest propagowanie wszystkich zmian w modelu aplikacji dla wszystkich powiązań z dowolnego podłączonego komponentu.
Poza tym: Istnieją dwa typy modeli: Wyświetl modele i Modele aplikacji. Model aplikacji jest połączony za pomocą powiązań @Input (). Model widoku jest tylko właściwością komponentu (nie ozdobioną @Input ()), która jest związana w szablonie komponentu.
Aby odpowiedzieć na twoje pytania:
Co się stanie, jeśli będę musiał komunikować się między elementami rodzeństwa?
Model współdzielonej aplikacji : Rodzeństwo może komunikować się za pośrednictwem modelu współdzielonej aplikacji (podobnie jak kątowy 1). Na przykład, gdy jedno rodzeństwo wprowadza zmiany w modelu, drugie rodzeństwo, które ma powiązania z tym samym modelem, jest automatycznie aktualizowane.
Zdarzenia komponentu : komponenty potomne mogą emitować zdarzenie do komponentu nadrzędnego za pomocą powiązań @Output (). Komponent nadrzędny może obsługiwać zdarzenie i manipulować modelem aplikacji lub własnym modelem widoku. Zmiany w modelu aplikacji są automatycznie propagowane do wszystkich komponentów, które bezpośrednio lub pośrednio wiążą się z tym samym modelem.
Zdarzenia serwisowe : składniki mogą subskrybować zdarzenia serwisowe. Na przykład dwa komponenty rodzeństwa mogą zasubskrybować to samo zdarzenie serwisowe i odpowiedzieć, modyfikując odpowiednie modele. Więcej na ten temat poniżej.
Jak mogę komunikować się między komponentem głównym a komponentem zagnieżdżonym na kilku poziomach głębokości?
- Współużytkowany model aplikacji : model aplikacji można przekazać z komponentu głównego do głęboko zagnieżdżonych podskładników za pomocą powiązań @Input (). Zmiany w modelu z dowolnego komponentu będą automatycznie propagowane do wszystkich komponentów, które współużytkują ten sam model.
- Zdarzenia serwisowe : możesz także przenieść EventEmitter do usługi współdzielonej, która pozwala dowolnemu komponentowi wstrzyknąć usługę i subskrybować zdarzenie. W ten sposób składnik główny może wywołać metodę usługi (zwykle mutującą model), która z kolei emituje zdarzenie. Kilka warstw w dół, składnik typu grand-child, który również wstrzyknął usługę i zasubskrybował to samo zdarzenie, może sobie z tym poradzić. Każda procedura obsługi zdarzeń, która zmienia wspólny model aplikacji, automatycznie propaguje się do wszystkich komponentów, które są od niego zależne. Jest to prawdopodobnie najbliższy odpowiednik
$scope.broadcast()
z Angulara 1. Kolejna sekcja opisuje ten pomysł bardziej szczegółowo.
Przykład obserwowalnej usługi, która wykorzystuje zdarzenia serwisowe do propagowania zmian
Oto przykład obserwowalnej usługi, która wykorzystuje zdarzenia usługi do propagowania zmian. Po dodaniu TodoItem usługa emituje zdarzenie powiadamiające swoich subskrybentów.
export class TodoItem {
constructor(public name: string, public done: boolean) {
}
}
export class TodoService {
public itemAdded$: EventEmitter<TodoItem>;
private todoList: TodoItem[] = [];
constructor() {
this.itemAdded$ = new EventEmitter();
}
public list(): TodoItem[] {
return this.todoList;
}
public add(item: TodoItem): void {
this.todoList.push(item);
this.itemAdded$.emit(item);
}
}
Oto, w jaki sposób składnik główny zasubskrybuje to wydarzenie:
export class RootComponent {
private addedItem: TodoItem;
constructor(todoService: TodoService) {
todoService.itemAdded$.subscribe(item => this.onItemAdded(item));
}
private onItemAdded(item: TodoItem): void {
// do something with added item
this.addedItem = item;
}
}
Komponent potomny zagnieżdżony na kilku poziomach w głębi zasubskrybowałby to wydarzenie w ten sam sposób:
export class GrandChildComponent {
private addedItem: TodoItem;
constructor(todoService: TodoService) {
todoService.itemAdded$.subscribe(item => this.onItemAdded(item));
}
private onItemAdded(item: TodoItem): void {
// do something with added item
this.addedItem = item;
}
}
Oto komponent, który wywołuje usługę w celu uruchomienia zdarzenia (może znajdować się w dowolnym miejscu w drzewie komponentów):
@Component({
selector: 'todo-list',
template: `
<ul>
<li *ngFor="#item of model"> {{ item.name }}
</li>
</ul>
<br />
Add Item <input type="text" #txt /> <button (click)="add(txt.value); txt.value='';">Add</button>
`
})
export class TriggeringComponent{
private model: TodoItem[];
constructor(private todoService: TodoService) {
this.model = todoService.list();
}
add(value: string) {
this.todoService.add(new TodoItem(value, false));
}
}
Odniesienie: Wykrywanie zmiany w kącie