Es tut uns leid, wenn dies hier bereits beantwortet wurde, aber ich konnte keine Übereinstimmung für unser spezielles Szenario finden.
Wir haben in unserem Entwicklungsteam eine Diskussion über Funktionsaufrufe in eckigen Vorlagen geführt. Als allgemeine Faustregel stimmen wir zu, dass Sie dies nicht tun sollten. Wir haben jedoch versucht zu diskutieren, wann es in Ordnung sein könnte. Lassen Sie mich Ihnen ein Szenario geben.
Angenommen, wir haben einen Vorlagenblock, der in eine ngIf eingeschlossen ist und nach mehreren Parametern sucht, wie hier:
<ng-template *ngIf="user && user.name && isAuthorized">
...
</ng-template>
Würde es einen signifikanten Leistungsunterschied im Vergleich zu so etwas geben:
Vorlage:
<ng-template *ngIf="userCheck()">
...
</ng-template>
Typoskript:
userCheck(): boolean {
return this.user && this.user.name && this.isAuthorized;
}
Um die Frage zusammenzufassen: Hätte die letzte Option erhebliche Leistungskosten?
Wir würden es vorziehen, den 2. Ansatz zu verwenden, wenn wir mehr als zwei Bedingungen überprüfen müssen. In vielen Online-Artikeln heißt es jedoch, dass Funktionsaufrufe in Vorlagen IMMER schlecht sind. Ist dies in diesem Fall wirklich ein Problem?
quelle
Antworten:
Ich habe auch versucht, Funktionsaufrufe in Vorlagen so weit wie möglich zu vermeiden, aber Ihre Frage hat mich zu einer schnellen Recherche inspiriert:
Ich habe einen weiteren Fall mit Caching-
userCheck()
Ergebnissen hinzugefügtHier wurde eine Demo vorbereitet: https://stackblitz.com/edit/angular-9qgsm9
Überraschenderweise scheint es keinen Unterschied zu geben
Und
Und
Dies scheint für eine einfache Eigenschaftsprüfung gültig zu sein, aber es wird definitiv einen Unterschied geben, wenn es um
async
Aktionen geht, zum Beispiel um Getter, die auf eine API warten.quelle
Dies ist eine ziemlich einfühlsame Antwort.
Die Verwendung solcher Funktionen ist durchaus akzeptabel. Dadurch werden die Vorlagen viel übersichtlicher und es entsteht kein erheblicher Overhead. Wie JB bereits sagte, wird es auch eine viel bessere Basis für Unit-Tests schaffen.
Ich denke auch, dass jeder Ausdruck, den Sie in Ihrer Vorlage haben, vom Änderungserkennungsmechanismus als Funktion ausgewertet wird. Es spielt also keine Rolle, ob Sie ihn in Ihrer Vorlage oder in Ihrer Komponentenlogik haben.
Halten Sie einfach die Logik innerhalb der Funktion auf ein Minimum. Wenn Sie jedoch Bedenken hinsichtlich der Auswirkungen einer solchen Funktion auf die Leistung haben, empfehle ich Ihnen dringend, Ihre
ChangeDetectionStrategy
zu verwendenOnPush
, was ohnehin als Best Practice gilt. Damit wird die Funktion nicht in jedem Zyklus aufgerufen, nur wenn sich etwasInput
ändert, ein Ereignis in der Vorlage auftritt usw.(mit etc, weil ich den anderen Grund nicht mehr kenne) .
Ich persönlich denke, es ist noch schöner, das Observables-Muster zu verwenden. Sie können dann die
async
Pipe verwenden, und nur wenn ein neuer Wert ausgegeben wird, wird die Vorlage neu bewertet:Sie können dann einfach in der Vorlage wie folgt verwenden:
Eine weitere Option wäre die Verwendung
ngOnChanges
, wenn alle von der Komponente abhängigen Variablen Eingaben sind und Sie eine Menge Logik haben, um eine bestimmte Vorlagenvariable zu berechnen (was nicht der Fall ist, den Sie gezeigt haben):Was Sie in Ihrer Vorlage wie folgt verwenden können:
quelle
Observable
Stream, der sie zu einem perfekten Kandidaten für die zweite Option macht, die ich gezeigt habe.Wird aus vielen Gründen der Auftraggeber nicht empfohlen:
Um festzustellen, ob userCheck () neu gerendert werden muss, muss Angular den Ausdruck userCheck () ausführen, um zu überprüfen, ob sich sein Rückgabewert geändert hat.
Da Angular nicht vorhersagen kann, ob sich der Rückgabewert von userCheck () geändert hat, muss die Funktion jedes Mal ausgeführt werden, wenn die Änderungserkennung ausgeführt wird.
Wenn die Änderungserkennung 300 Mal ausgeführt wird, wird die Funktion 300 Mal aufgerufen, auch wenn sich ihr Rückgabewert nie ändert.
Erweiterte Erklärung und weitere Probleme https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496
Das Problem, das auftritt, wenn Ihre Komponente groß ist und an vielen Änderungsereignissen teilnimmt, wenn Ihre Komponente klein ist und nur an einigen Ereignissen teilnimmt, sollte kein Problem sein.
Beispiel mit Observablen
Dann können Sie es die mit asynchroner Pipe beobachtbare Pipe in Ihrem Code verwenden.
quelle
Ich denke, dass JavaScript mit dem Ziel erstellt wurde, dass ein Entwickler den Unterschied zwischen einem Ausdruck und einem Funktionsaufruf in Bezug auf die Leistung nicht bemerkt.
In C ++ gibt es ein Schlüsselwort
inline
zum Markieren einer Funktion. Zum Beispiel:Dies wurde durchgeführt, um einen Funktionsaufruf zu eliminieren. Infolgedessen ersetzt der Compiler alle Aufrufe von
userCheck
durch den Hauptteil der Funktion. Grund zur Innovationinline
? Ein Leistungsschub.Daher denke ich, dass die Ausführungszeit eines Funktionsaufrufs mit einem Ausdruck wahrscheinlich langsamer ist als die Ausführung nur des Ausdrucks. Ich denke aber auch, dass Sie keinen Leistungsunterschied bemerken werden, wenn Sie nur einen Ausdruck in der Funktion haben.
quelle