Luego de de una prolongada compilación de datos solucionamos esta pregunta que pueden tener ciertos de nuestros usuarios. Te brindamos la respuesta y esperamos servirte de gran apoyo.
Solución:
También traté de evitar llamadas a funciones en plantillas tanto como sea posible, pero su pregunta me inspiró a hacer una investigación rápida:
Agregué otro caso con almacenamiento en caché. userCheck()
resultados
*ngIf="isUserChecked"
...
// .ts
isUserChecked = this.userCheck()
Preparé una demostración aquí: https://stackblitz.com/edit/angular-9qgsm9
Sorprendentemente parece que no hay diferencia entre
*ngIf="user && user.name && isAuthorized"
Y
*ngIf="userCheck()"
...
// .ts
userCheck(): boolean
return this.user && this.user.name && this.isAuthorized;
Y
*ngIf="isUserChecked"
...
// .ts
isUserChecked = this.userCheck()
Parece que esto es válido para una verificación de propiedad simple, pero definitivamente habrá una diferencia si se trata de alguna async
acciones, captadores que están esperando alguna API, por ejemplo.
Esta es una respuesta bastante obstinada.
El uso de funciones como esta es perfectamente aceptable. Hará que las plantillas sean mucho más claras y no causará ninguna sobrecarga significativa. Como dijo JB antes, también establecerá una base mucho mejor para las pruebas unitarias.
También creo que cualquier expresión que tenga en su plantilla será evaluada como una función por el mecanismo de detección de cambios, por lo que no importa si la tiene en su plantilla o en la lógica de su componente.
Simplemente mantenga la lógica dentro de la función al mínimo. Sin embargo, si desconfía de cualquier impacto en el rendimiento que pueda tener una función de este tipo, le recomiendo encarecidamente que ponga su ChangeDetectionStrategy
para OnPush
, que se considera la mejor práctica de todos modos. Con esto, la función no será llamada cada ciclo, solo cuando un Input
cambia, ocurre algún evento dentro de la plantilla, etc.
(usando, etc., porque ya no sé la otra razón).
Personalmente, nuevamente, creo que es incluso mejor usar el patrón Observables, luego puedes usar el async
tubería, y solo cuando se emite un nuevo valor, la plantilla se vuelve a evaluar:
userIsAuthorized$ = combineLatest([
this.user$,
this.isAuthorized$
]).pipe(
map(([ user, authorized ]) => !!user && !!user.name && authorized),
shareReplay( refCount: true, bufferSize: 1 )
);
A continuación, puede simplemente utilizar en la plantilla de esta manera:
...
Otra opción sería utilizar ngOnChanges
si todas las variables dependientes del componente son Entradas, y tiene mucha lógica para calcular una determinada variable de plantilla (que no es el caso que mostró):
export class UserComponent implements ngOnChanges
userIsAuthorized: boolean = false;
@Input()
user?: any;
@Input()
isAuthorized?: boolean;
ngOnChanges(changes: SimpleChanges): void changes.isAuthorized)
this.userIsAuthorized = this.userCheck();
userCheck(): boolean false;
Que puedes usar en tu plantilla así:
...
No es recomendable por muchas razones el principal:
Para determinar si userCheck() debe volver a procesarse, Angular debe ejecutar la expresión userCheck() para verificar si su valor de retorno ha cambiado.
Debido a que Angular no puede predecir si el valor de retorno de userCheck() ha cambiado, debe ejecutar la función cada vez que se ejecuta la detección de cambios.
Entonces, si la detección de cambios se ejecuta 300 veces, la función se llama 300 veces, incluso si su valor de retorno nunca cambia.
Explicación extendida y más problemas https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496
El problema surge cuando si su componente es grande y asiste a muchos eventos de cambio, si su componente es pequeño y solo asiste a algunos eventos, no debería ser un problema.
Ejemplo con observables
user$;
isAuth$
userCheck$;
userCheck$ = user$.pipe(
switchMap((user) =>
return forkJoin([of(user), isAuth$]);
)
.map(([user, isAuthenticated])=>
if(user && user.name && isAuthenticated)
return true;
else
return false;
)
);
Luego puede usarlo como observable con tubería asíncrona en su código.
Al final de todo puedes encontrar las anotaciones de otros administradores, tú también eres capaz insertar el tuyo si te apetece.