Menu

Angular: Entendiendo la detección de cambios.

angularservicio - August 13, 2018 por Carlos Rojas | Edita este Post.
Angular CLI6.1.1

Cada vez que nuestros usuarios realizan alguna acción a través de nuestros componentes, Angular se encarga de detectar los diferentes cambios para mantener la vista de nuestros usuarios actualizada.

¿ Que es la detección de cambios en Angular ?

La detección de cambios es un mecanismo donde Angular observa el estado interno de las estructuras de datos (Objetos, Array, etc) en un App y lo hace visible en la vista.

En Angular una aplicación es un arbol de componentes donde componentes padres contienen componentes hijos y asi sucesivamente.

y cada componente tiene un detector de cambios responsable por el chequeo de los bindings definidos en su template.

Los cambios en los estados de una App pueden ser causados por tres cosas:

Eventos: Click, Submit, MouseOver, etc.

XHR: Peticiones para buscar info en APIs.

Timers: setTimeout(), setInterval().

Todos son asincronos y deben ser detectados para asegurar el correcto funcionamiento de nuestra App.

¿ Como se lleva a cabo la detección de Cambios ?

Como dijimos anteriormente todos los componentes tienen un CD asociado y funciona como un arbol de padres e hijos.

Ahora digamos que el usuario hizo un click en un componente, esto notifica a Angular que se efectuo una acción del usuario y alerta a todos los CD de arriba hacia abajo.

Algo interesante es que al realizar la detección de cambios de arriba hacia abajo nos da predictibilidad en el resultado. Ahora te estaras preguntando Angular tiene que recorrer todo el arbol para notificar de cambios a todos los componentes? La respuesta es que por defecto Si pero se puede mejorar utilizando Objetos inmutables y/o Observables.

Objetos inmutables.

Podemos saltar algunos chequeos si por ejemplo un componente solo depende de un input() que no cambia.

@Component({
  template: `
    <h2></h2>
    <span></span>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
class VCardCmp {
  @Input() vData;
}

Para decirle a Angular que el componente no cambia le hemos agregado la estrategia de detección OnPush. y de esta manera si tenemos un arbol muy grande de componentes podriamos ahorrarnos muchos chequeos.

Observables.

Los observables son una manera moderna de interactuar con APIs y eventos y nos permite observar los cambios sobre un flujo de datos. Supongamos el siguiente componente.

@Component({
  template: '',
  changeDetection: ChangeDetectionStrategy.OnPush
})
class CartBadgeCmp {

  @Input() addItemStream:Observable<any>;
  counter = 0;

  ngOnInit() {
    this.addItemStream.subscribe(() => {
      this.counter++; // application state changed
    })
  }
}

Pero debido a que hemos seleccionado su estrategia de cambio a onPush() un evento no disparara el CD del componente. Para ajustar esto debemos utilizar el componente ChangeDetectorRef y el metodo markForCheck(). el cual le dice a Angular que lo tenga en cuenta en el chequeo de cambios. haciendo los cambios respectivos nuestro componente debe quedar como sigue.

@Component({
  template: '',
  changeDetection: ChangeDetectionStrategy.OnPush
})
class CartBadgeCmp {

  @Input() addItemStream:Observable<any>;
  counter = 0;

  constructor(private cd: ChangeDetectorRef) {}

  ngOnInit() {
    this.addItemStream.subscribe(() => {
      this.counter++; // application state changed
      this.cd.markForCheck(); // marks path
    })
  }
}

y de esta manera obtendriamos algo asi.

Bueno esto es todo por el dia de hoy, espero haya sido de utilidad :)

Referencias.

ANGULAR CHANGE DETECTION EXPLAINED

Change Detection in Angular

¡Compártelo!