typescript - Uso de variables setter y getter en HTML (componente de Angular)
Creé un componente angular simple para probar el uso de una variable que utiliza un estilo getter/setter:
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
_name = 'Variable Example';
get name(): string {
console.log("GET!!!");
return this._name;
}
set name(value:string): void {
this._name = value;
}
}
Luego, uso esta variable en el HTML:
<p>
{{ name }}
</p>
Lo que noté es que el get name() se llama 4 veces (revisa en vivo aquí)
¿Existen algunas reglas de mejores prácticas que indiquen que no se deberían usar getter y setters en componentes HTML? ¿Tendré problemas de rendimiento al usar este enfoque?
¡Gracias!
PD: Este no es el escenario real, solo es un pequeño ejemplo de lo que estoy haciendo.
Respuesta #1
ACTUALIZACIÓN: Ahora con Signals, esta discusión finalmente ha terminado de manera definitiva. Usa computed en lugar de getters y entradas de señales y tendrás garantizado un buen rendimiento y código declarativo. Mi respuesta a continuación sigue siendo relevante para cuando no puedas usar señales por alguna razón, como una versión antigua de Angular, falta de tiempo para refactorizar o llamadas a funciones que toman argumentos de la plantilla.
Aquí están mis reglas generales que me han servido muy bien:
Siempre usa la estrategia de detección de cambios
OnPushpara evitar verificaciones innecesariasSiempre usa datos inmutables, actualiza todo el array/objeto en cualquier cambio. Busca en Google 'inmutabilidad' si no estás familiarizado con ello, es muy útil y obligatorio para
OnPush.Nunca almacenes estados que se puedan calcular. Si se puede calcular usando, por ejemplo, los @Inputs de un componente, opta por un getter. Calcular un getter simple con matemáticas o recorriendo un arreglo pequeño es muy rápido y te ahorra el problema de sincronizar estados. Hice pruebas de rendimiento en Firefox, un getter simple que recorre un arreglo de 100 elementos se ejecuta 7 millones de veces por segundo. Generalmente, los getters no serán un cuello de botella en tu aplicación y son mucho más fáciles de manejar, en lugar de actualizar estados en los hooks del ciclo de vida. Pero sigue leyendo.
Si tu estado calculado produce un nuevo arreglo o objeto, siempre usa pipe puro para evitar recálculos innecesarios, ya que es una operación mucho más pesada y no es adecuada para un getter.
Si tu getter no va a cambiar, considera el patrón de inicialización perezosa: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters
Evita ngOnChange a favor de los setters en @Inputs: de esta manera tus cambios se propagan más "directamente". Algo cambió: las cosas relacionadas se actualizan, en lugar de "provocar efectos secundarios" en algún hook para ser llamado más tarde. A menos que necesites reaccionar a múltiples inputs que cambian al mismo tiempo.
AVISO: Estos son solo mis pensamientos sobre el asunto que he desarrollado durante un par de años trabajando con Angular en proyectos complejos.
Puedes leer más sobre el enfoque declarativo en la escritura de código Angular en este artículo que escribí: https://indepth.dev/compliant-components-declarative-approach-in-angular/
Respuesta #2
Debes evitar llamar métodos/getter desde tu plantilla porque el método se llamará cada vez que se ejecute la detección de cambios.
En su lugar, deberías calcular lo que quieras dentro de algo como ngOnInit y asignarlo a una variable o usar un pipe.
Si quieres calcular cada vez que tu valor cambie, deberías usar un pipe ya que se llamaría solo cuando los valores de entrada cambien y no cada vez que se ejecute la detección de cambios.