Désolé si cela a déjà été répondu ici, mais je n'ai trouvé aucune correspondance pour notre scénario spécifique, alors c'est parti!
Nous avons eu une discussion dans notre équipe de développement, concernant les appels de fonction dans les modèles angulaires. Maintenant, en règle générale, nous convenons que vous ne devriez pas faire cela. Cependant, nous avons essayé de discuter du moment où cela pourrait aller. Permettez-moi de vous donner un scénario.
Disons que nous avons un bloc de modèle qui est enveloppé dans un ngIf, qui vérifie plusieurs paramètres, comme ici:
<ng-template *ngIf="user && user.name && isAuthorized">
...
</ng-template>
Y aurait-il une différence significative de performances par rapport à quelque chose comme ceci:
Modèle:
<ng-template *ngIf="userCheck()">
...
</ng-template>
Manuscrit:
userCheck(): boolean {
return this.user && this.user.name && this.isAuthorized;
}
Donc, pour résumer la question, la dernière option aurait-elle un coût de performance significatif?
Nous préférerions utiliser la 2ème approche, dans les situations où nous devons vérifier plus de 2 conditions, mais de nombreux articles en ligne disent que les appels de fonction sont TOUJOURS mauvais dans les modèles, mais est-ce vraiment un problème dans ce cas?
la source
Réponses:
J'ai également essayé d'éviter autant que possible les appels de fonctions dans les modèles, mais votre question m'a inspiré à faire une recherche rapide:
J'ai ajouté un autre cas avec des
userCheck()
résultats de mise en cacheJ'ai préparé une démo ici: https://stackblitz.com/edit/angular-9qgsm9
Étonnamment, il semble qu'il n'y ait pas de différence entre
Et
Et
Cela semble valide pour une simple vérification de propriété, mais il y aura certainement une différence s'il s'agit d'
async
actions, des getters qui attendent une API par exemple.la source
Ceci est une réponse assez réfléchie.
L'utilisation de fonctions comme celle-ci est parfaitement acceptable. Cela rendra les modèles beaucoup plus clairs et ne causera pas de surcharge importante. Comme JB l'a dit auparavant, cela établira également une bien meilleure base pour les tests unitaires.
Je pense également que quelle que soit l'expression que vous avez dans votre modèle, elle sera évaluée en fonction par le mécanisme de détection des changements, donc peu importe si vous l'avez dans votre modèle ou dans la logique de votre composant.
Gardez la logique à l'intérieur de la fonction au minimum. Si vous vous méfiez toutefois de tout impact sur les performances qu'une telle fonction pourrait avoir, je vous conseille vivement de le
ChangeDetectionStrategy
faireOnPush
, ce qui est de toute façon considéré comme la meilleure pratique. Avec cela, la fonction ne sera pas appelée à chaque cycle, uniquement lorsqu'unInput
changement, un événement se produit à l'intérieur du modèle, etc.(en utilisant etc, parce que je ne connais plus l'autre raison) .
Personnellement, encore une fois, je pense qu'il est encore plus agréable d'utiliser le modèle Observables, vous pouvez ensuite utiliser le
async
tuyau, et seulement lorsqu'une nouvelle valeur est émise, le modèle est réévalué:Vous pouvez ensuite simplement utiliser dans le modèle comme ceci:
Une autre option serait d’utiliser
ngOnChanges
, si toutes les variables dépendantes du composant sont des entrées, et que vous avez beaucoup de logique pour calculer une certaine variable de modèle (ce qui n'est pas le cas que vous avez montré):Que vous pouvez utiliser dans votre modèle comme ceci:
la source
Observable
flux, ce qui en fera un candidat parfait pour la 2ème option que j'ai montrée. Quoi qu'il en soit, je suis heureux de pouvoir vous donner quelques idéesN'est pas recommandé pour de nombreuses raisons, le principal:
Pour déterminer si userCheck () doit être restitué, Angular doit exécuter l'expression userCheck () pour vérifier si sa valeur de retour a changé.
Dans la mesure où Angular ne peut pas prédire si la valeur de retour de userCheck () a changé, il doit exécuter la fonction à chaque exécution de la détection de changement.
Ainsi, si la détection des modifications s'exécute 300 fois, la fonction est appelée 300 fois, même si sa valeur de retour ne change jamais.
Explication étendue et autres problèmes https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496
Le problème qui se pose lorsque si votre composant est important et participe à de nombreux événements de changement, si votre composant est peu important et ne participe qu'à quelques événements ne devrait pas être un problème.
Exemple avec observables
Ensuite, vous pouvez l'utiliser dans le code observable avec async.
la source
Je pense que JavaScript a été créé avec un objectif afin qu'un développeur ne remarque pas la différence entre une expression et un appel de fonction en termes de performances.
En C ++, il existe un mot-clé
inline
pour marquer une fonction. Par exemple:Cela a été fait afin d'éliminer un appel de fonction. Par conséquent, le compilateur remplace tous les appels de
userCheck
par le corps de la fonction. Pourquoi innoverinline
? Une amélioration des performances.Par conséquent, je pense que le temps d'exécution d'un appel de fonction avec une expression, probablement, est plus lent que l'exécution de l'expression uniquement. Mais, je pense également que vous ne remarquerez pas de différence de performance si vous n'avez qu'une seule expression dans la fonction.
la source