¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
dev
Eider Ogueta 13/02/2025 Cargando comentarios…
La detección de cambios es el proceso a través del cual Angular verifica si el estado de su aplicación ha cambiado y si es necesario actualizar algún DOM.
Cada componente de Angular tiene su propio detector de cambios y puedes ver toda la aplicación Angular como un árbol de componentes.
Angular ejecuta su mecanismo de detección de cambios, de arriba a abajo en el árbol, para que los cambios en el modelo de datos se reflejen en la vista de una aplicación.
Resulta que estas tres cosas tienen algo en común, son todas asíncronas.
Estos son los únicos casos en los que Angular está realmente interesado en actualizar la vista.
Déjame que te presente a nuestro protagonista: zone.js, que es básicamente un contexto de ejecución para operaciones asíncronas.
Angular tiene su propia implementación de zone.js para hacer eso, un servicio llamado NgZone. Este servicio crea una zona denominada “zona angular” y, cuando el código se ejecuta dentro de esta zona, el mecanismo de detección de cambios de Angular se activa automáticamente y la vista se actualiza en consecuencia.
Esta verificación de detección de cambios (la mayor parte de las veces innecesaria) genera problemas de rendimiento cuando se trabaja con proyectos grandes o se maneja una enorme cantidad de datos, dando como resultado una experiencia de usuario muy mala.
Aquí viene lo interesante, veamos cómo podemos reducir las llamadas de detección de cambios en su aplicación.
NgZone, como hemos visto antes, es un servicio proporcionado por Angular que ayuda a administrar y controlar la ejecución de tareas asincrónicas y la detección de cambios.
El uso más común de este servicio es optimizar el rendimiento al iniciar un trabajo que consta de una o más tareas asincrónicas que no requieren actualizaciones de UI o manejo de errores para ser manejado por Angular. Estas tareas se pueden iniciar mediante runOutsideAngular() y, si es necesario, se pueden volver ejecutar dentro de la zona Angular mediante run().
Cualquier tarea o micro-tarea futura programada desde esta función continuará ejecutándose dentro/fuera de la zona Angular.
import { Component , NgZone } de '@angular/core' ;
@Component ({
selector : 'app-example' ,
template : `
<button (click)="onClick()">Ejecutar código dentro de NgZone</button>
` ,
})
export class ExampleComponent {
constructor ( private ngZone: NgZone ) {}
onClick ( ) {
this . ngZone . run ( () => {
// Código ejecutado dentro de NgZone
// Se activa la detección de cambios de Angular
});
}
}
En el siguiente enlace podemos ver un ejemplo muy interesante de este servicio.
Cada componente tiene su propia detección de cambios:
changeName() {
// this.user.name = 'Alexandra'; -> Mutar un objeto existente
this.user = { // -> Proporcionar una referencia nueva
name: 'Alexandra'
};
}
Hay una forma más agresiva para reducir las comprobaciones de un componente y su subárbol: separar el detector de cambios del componente.
constructor(private cd: ChangeDetectorRef){
this.cd.detach(); // Angular no ejecutará el detector de cambios para este componente
}
ChangeDetectorRef es una clase base que proporciona funcionalidad de detección de cambios. El árbol de detección de cambios recopila todas las vistas que se van a comprobar en busca de cambios.
Esta clase te proporciona métodos para agregar y eliminar vistas del árbol, iniciar la detección de cambios y marcar explícitamente las vistas como “dirty”, lo que significa que han cambiado y deben volver a procesarse.
Puedes encontrar más información sobre los métodos de la clase en la web de Angular.
Bueno, y... ¡qué mejor manera de entender esto que de manera práctica!
La siguiente aplicación se va a componer de un reloj que actualiza la hora cada segundo y una tabla donde se va a mostrar una lista de usuarios obtenidos de un servicio. Así mismo, este componente está formado por el componente fila, que se encarga de mostrar los datos de cada usuario y de generar un id radom para cada uno de ellos.
Puedes encontrar la aplicación en el siguiente enlace.
Al ejecutar la aplicación, podemos observar que la columna Random va a generar de manera ilimitada un número por cada fila. Pero realmente el código no está definido con esa finalidad.
Esto es debido a que el componente hour está asignando un valor nuevo a la variable time cada segundo, disparando la detección de cambios. Por defecto, todos los componentes tienen definido ChangeDetectionStrategy.Default y se actualizan la vistas de todos ellos ejecutando a su vez la función getRandom().
Para evitarlo, definimos la estrategia de detección de cambios del componente row.component.ts a ChangeDetectionStrategy.OnPush (línea 12).
Con ello, conseguimos que los datos de la tabla se modifiquen cuando se produce un cambio de datos en el observable, en este caso cada vez que se llama a la función getUsers().
Espero que este post te haya sido útil para comprender el funcionamiento de la magia de Angular y darte cuenta de que un diseño deficiente puede afectar negativamente el rendimiento a medida que tu aplicación crece.
Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.
Cuéntanos qué te parece.