Non esiste un equivalente da $scope.emit()
o $scope.broadcast()
verso AngularJS. EventEmitter all'interno di un componente si avvicina, ma come hai detto, emetterà un evento solo al componente genitore immediato.
In angolare, ci sono altre alternative che proverò a spiegare di seguito.
I bind @Input () consentono di collegare il modello di applicazione in un grafico a oggetti diretto (da radice a foglie). Il comportamento predefinito della strategia del rilevatore di modifiche di un componente è di propagare tutte le modifiche a un modello di applicazione per tutti i binding da qualsiasi componente collegato.
A parte: ci sono due tipi di modelli: Visualizza modelli e Modelli di applicazione. Un modello di applicazione è collegato tramite collegamenti @Input (). Un modello di vista è solo una proprietà del componente (non decorata con @Input ()) che è associata al modello del componente.
Per rispondere alle tue domande:
Cosa succede se devo comunicare tra i componenti dei fratelli?
Modello di applicazione condiviso : i fratelli possono comunicare attraverso un modello di applicazione condiviso (proprio come l'angolo 1). Ad esempio, quando un fratello effettua una modifica a un modello, l'altro fratello che ha i collegamenti allo stesso modello viene automaticamente aggiornato.
Eventi componente : i componenti figlio possono emettere un evento al componente padre usando i collegamenti @Output (). Il componente padre può gestire l'evento e manipolare il modello dell'applicazione o il proprio modello di visualizzazione. Le modifiche al modello di applicazione vengono propagate automaticamente a tutti i componenti che si legano direttamente o indirettamente allo stesso modello.
Eventi di servizio : i componenti possono iscriversi agli eventi di servizio. Ad esempio, due componenti di pari livello possono abbonarsi allo stesso evento di servizio e rispondere modificando i rispettivi modelli. Maggiori informazioni su questo sotto.
Come posso comunicare tra un componente Root e un componente nidificato a diversi livelli di profondità?
- Modello di applicazione condivisa : il modello di applicazione può essere passato dal componente Root ai componenti secondari profondamente nidificati tramite i collegamenti @Input (). Le modifiche a un modello da qualsiasi componente si propagheranno automaticamente a tutti i componenti che condividono lo stesso modello.
- Eventi di servizio : è anche possibile spostare EventEmitter su un servizio condiviso, che consente a qualsiasi componente di iniettare il servizio e iscriversi all'evento. In questo modo, un componente Root può chiamare un metodo di servizio (in genere mutando il modello), che a sua volta emette un evento. Diversi livelli in basso, un componente grand-child che ha anche iniettato il servizio e sottoscritto lo stesso evento, può gestirlo. Qualsiasi gestore di eventi che modifica un modello di applicazione condiviso, si propaga automaticamente a tutti i componenti che dipendono da esso. Questo è probabilmente l'equivalente più vicino a
$scope.broadcast()
da Angolare 1. La sezione successiva descrive questa idea in modo più dettagliato.
Esempio di un servizio osservabile che utilizza gli eventi di servizio per propagare le modifiche
Ecco un esempio di un servizio osservabile che utilizza eventi di servizio per propagare le modifiche. Quando viene aggiunto un TodoItem, il servizio emette un evento che notifica ai suoi abbonati componenti.
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);
}
}
Ecco come un componente root si iscriverebbe all'evento:
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;
}
}
Un componente figlio nidificato a più livelli si iscriverebbe all'evento allo stesso modo:
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;
}
}
Ecco il componente che chiama il servizio per attivare l'evento (può risiedere ovunque nella struttura dei componenti):
@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));
}
}
Riferimento: rilevamento del cambiamento in angolare