Digamos que tengo una function noificationHandler() en mi service.ts que está fuera del contexto de angular. noificationHandler() es invocado por un tercero y noificationHandler() básicamente consume una matriz y emite la matriz a los componentes que se han suscrito a su servicio.
servicio.ts
public mySubject: Subject<any> = new Subject(); public myObservable = this.mySubject.asObservable(); constructor() { this.registry.subscribe("notification.msg",this.noificationHandler.bind(this)); } noificationHandler(data) { this.publishUpdate(data) } publishUpdate(data) { this.mySubject.next(data); }componente.ts
constructor(private service: myService) { this.service.myObservable.subscribe(list => { this.list = list; }); }^^^ en este punto la plantilla no se actualiza con los nuevos datos
Dado que "notification.msg" está fuera de la zona de angular, la detección de cambios de angular no se ejecuta cuando se invoca este evento ("notification.msg") .
Ahora hay 2 formas de invocar la detección de cambios.
1) noificationHandler() dentro de zone.run() de angular
this.registry.subscribe("a2mevent.notification.msg", this.ngZone.run(() => this.noificationHandler.bind(this)));2) Pidiendo individualmente al componente que detecte cambios
constructor(private service: myService, private ref: ChangeDetectorRef) { this.service.myObservable.subscribe(list => { this.list = list; this.ref.detectChanges(); // <==== manually invoking change detection }); }¡Ambas opciones funcionan! Y mi estructura de componentes es la siguiente
A --> root component B C D // my component is here (4 levels of nesting)Preguntas -
1) ¿DetectChanges() detectará los cambios solo para sus propios componentes o también ejecutará la detección de cambios en los componentes secundarios?
2) ¿zone.run() activará la detección de cambios de todos los componentes desde la raíz hasta la hoja?
Entre zone.run() y detectChanges() tengo curiosidad por saber cuál es mejor en rendimiento .
ApplicationRef.tick (igual que setTimeout() ) y zone.run() provocan la detección de cambios en toda la aplicación. También los detectores de eventos agregados dentro de Angular o por Angular (usando enlaces de vista o @HostBinding() causan la detección de cambios para toda la aplicación.
ChangeDetectorRef.detectChanges ejecuta la detección de cambios para un componente específico (y sus descendientes, si corresponde, por ejemplo, debido a enlaces de entrada)
Si algún código que se ejecuta fuera de la zona de Angular llama al código de Angular y cambia el estado, entonces la detección de cambios debe invocarse explícitamente porque Angular no tiene forma de saber que el estado cambió.
Si el cambio de estado es local para un componente (por ejemplo, un campo de componentes), ChangeDetectorRef.detectChanges o ChangeDetectorRef.markforCheck son más eficientes.
Si la llamada desde el exterior, por ejemplo, navega a una ruta diferente, esto puede tener consecuencias para una serie de componentes, y tampoco está claro cuándo se completa todo el cambio de ruta porque podría causar llamadas asincrónicas (y devoluciones de llamadas). En este caso zone.run() es la mejor opción, porque el código invocado directa e indirectamente (como devoluciones de llamada de observables y promesas) invocado se ejecutará dentro de la zona de Angular y Angular los reconocerá e invocará la detección de cambios automáticamente.
Ambos son cosas totalmente diferentes.
NgZone es una biblioteca que proporciona zonas para su aplicación para que pueda ejecutar las instancias en múltiples ámbitos.
ChangeDetection siempre es de padre a hoja como A > B > C Cuando llama a detectChanges(), invocará el componente actual y sus componentes secundarios también. Por lo tanto, este es el mejor enfoque para usar OnPush changesdetectionStrategy para componentes de hoja, por lo que solo detectarán cambios cuando se actualicen las entradas.
Además, ApplicationRef es similar a ChangeDetector; la diferencia es que detectará cambios desde el componente raíz hasta el último componente secundario.
ChaneDetection y NgZone es la mejor combinación siempre para evitar el ChangeDetection innecesario