2016-01-26 19 views
8

Dziś musiałem rozwiązać problem z wydajnością spowodowane przez ten kod: Przestrzegać UpdateStats zwanych wewnątrz szablonuFunkcja wewnątrz szablonu jest nazywane wiele razy (Angular JS)

<script type="text/ng-template" id="entityGrouper"> 

<section> 

<div> 
<ul ng-click="hideEntityBox = !hideEntityBox"> 
<li> 
{{ entityNode.name }} 
</li> 
<li ng-repeat="breadcrumbItem in entityNode.breadcrumb"> 
{{ breadcrumbItem }} 
</li> 
</ul> 
{{ updateStats(entityNode) }} 
<span ng-include="'/mypath/views/resume.html'"></span> 
</div> 

<div> 

<div ng-repeat="entityNode in entityNode.group" ng-include="'entityGrouper'"></div> 
<div ng-repeat="entity in entityNode.group" ng-include="'entityBox'"></div> 

</section> 

</script> 

użycie szablonu:

<div ng-repeat="entityNode in entityNode.group" ng-include="'entityGrouper'"></div> 

Po debugowaniu tego kodu odkryłem, że ta funkcja została wywołana o wiele więcej czasu niż rozmiar tablicy (moja tablica ma 4 obiekty, a funkcja była wywoływana ponad 100 razy), nawet po najechaniu myszką nazwała tę funkcję. Naprawiłem to poprzez wstawienie ng-init do szablonu i teraz działa poprawnie, ale nie zrozumiałem, dlaczego ta funkcja została wywołana tyle razy. Czy jest coś w dwukierunkowym powiązaniu danych?

+0

Czy rekursywnie wywołujesz ten sam szablon? znowu jest wywołanie '

' wewnątrz szablonu – Developer

Odpowiedz

1

Dzieje się tak nie dlatego, dwukierunkowych wiązania danych (ma zastosowanie do utworzenia wejścia), ale raczej z powodu wykrycia zmian kątowej. Kątowy okresowo sprawdza, czy którakolwiek z wartości związanych z szablonem uległa zmianie, a jeśli tak - aktualizuje jej wartość w widoku. Zazwyczaj jest on wyzwalany przez zdarzenia generowane przez użytkownika. Aby sprawdzić, czy zmieniono wartość updateStats(entityNode), Angular ją ocenia, co powoduje trafienie wydajności.

Aby to naprawić, można użyć wcześniej wspomnianego jednorazowego wiązania updateStats(entityNode), jeśli wynik zostanie ustawiony raz i nigdy się nie zmieni w przyszłości. Zgaduję, że to jest twoja sprawa, a już przeniosłeś ocenę na ng-init. W przypadku wartości aktualizowanych w czasie lepiej byłoby utworzyć osobną właściwość w postaci entityNode, np. entityNode.stats, wyświetlić w szablonie i uruchomić updateStats(entityNode) w kontrolerze lub usłudze tylko w razie potrzeby. W ten sposób zapobiegniesz uruchomieniu updateStats(entityNode) w każdym cyklu trawienia (już widziałeś, jak często to jest), a tym samym poprawiasz wydajność aplikacji.

4

Zazwyczaj zaleca się użycie $watch dla takich scenariuszy. Ponieważ wiążesz funkcję {{updateStats()}}, będzie ona wykonywana w każdym cyklu trawienia.

Tak więc w twoim kodzie, gdy wywoływany jest cykl skrótu, wywoła on także funkcję. Cykle trawienia są często nazywane wewnętrznie w Angular.

+0

to powinno być zaakceptowaną poprawną odpowiedzią: – thiagoh

2

To, co widzisz, jest wynikiem cyklu trawienia.

Dodanie :: spowoduje wywołanie funkcji jednokrotnego wiązania.

{{ ::updateStats(entityNode) }}

+0

co: dokładnie zrobić? –

+1

'' 'oferuje jednorazowe wiązanie. Jeśli przedrostkujesz wyrażenie, przestanie ono działać lub będzie się ponownie obliczać po pierwszym trawieniu. Więcej informacji * Sekcja jednorazowego wiązania * dokumentacji (https://docs.angularjs.org/guide/expression). –