2015-03-16 8 views
9

Jestem nowy w Angular, ale już słyszałem (i read) niektóre "plotki" na temat jego modelu renderowania i jak to się różni od na przykład React.Czy Angular używa rozszerzenia DOM, czy musi "renderować ponownie" każdy element listy?

Czytałem niektóre posty ekspertów Angular, którzy twierdzą, że jeśli musisz renderować długie listy z Angular, może to być powolne, ponieważ Angular ponownie wyświetli całą listę, jeśli coś się zmieni, podczas gdy React (na przykład) "nie wyrenderuje całej listy od zera po jej wyrenderowaniu, ale będzie wewnętrznie śledzić wyrenderowane elementy DOM, a po nowym wywołaniu utworzyć nowy wirtualny DOM, porównać go z poprzednim i zastosować tylko zmiany"

(cytat z losowym blogu o kątowe kwestii rendering)

Więc jak zacząłem uczyć kątowe, moją pierwszą rzeczą było wypróbowanie tego.

I wydaje się, że nie mogę odtworzyć problem ...

Oto obojętne Plunker które created odtworzyć problem.

Można dodać nowe elementy do listy wiadomości, które są renderowane z ng-powtarzać tak:

<table> 
    <tr ng-repeat="m in messages" class="{{name}}"> 
    <td>{{m.message}}</td> 
    <td>{{m.date}}</td> 
    </tr> 
</table> 

Możesz kliknąć na przycisk, który można zaktualizować jeden taki element, a można aktualizować inną nieruchomość który jest całkowicie niezwiązany z listą (name)

Teraz, jeśli otworzę pasek narzędzi dla programistów i zmodyfikuję atrybuty HTML przedmiotu w tabeli, a następnie kliknę "dodaj nową wiadomość", moje modyfikacje nie zostaną zgubione lub nadpisane przez Angular - wydaje się, że Angular nie w pełni renderuje DOM. Wydaje się dość sprytny.

Czy Angular zaczął ostatnio używać rozszerzenia DOM? (Moje demo używa Angulara 1.4.0 beta)

Właśnie dlatego, że z punktu widzenia renderowania DOM, po prostu nie widzę dużej różnicy między React i Angular.

Czy możesz pokazać mi przypadek użycia, który pokazuje wady modelu renderingu Angular?

+4

Nie wydaje mi się to "zbyt szerokie". Podstawowe pytanie, jakie zadaje OP, dotyczy * specyficznego * mechanika Angulara .. – user2864740

+3

Twoje pytania są dość szerokie, ponieważ naprawdę zadają kilka pytań i mogą być lepiej dopasowane do Programmers SE. W każdym razie Angular nie różni się od React, ale powtórzenie ng nie nadąża za tym, co się powtarza i związanymi z nim elementami. Zmieni to tylko to, co należy zmienić. Zobacz opcję 'track by' z' ng-repeat'. Skuteczność śledzenia Angulara w tej sprawie polega na tym, że duplikaty nie są dozwolone w 'ng-repeat', chyba że użyjesz opcji' track by', aby zmienić to, co zegarki Angular utrzymują synchronizację. – m59

+5

Badanie prawdziwości postów na blogu, które zawierają bezpodstawne stwierdzenia dotyczące niektórych technologii, nie jest tak naprawdę naszą specjalnością, ani specjalnością programisty.SE. –

Odpowiedz

6

Jest sporo zamieszania w odniesieniu do tego tematu, głównie dlatego, że nie jest to prosta odpowiedź typu "kątowe ponownie renderuje wszystko".

Podstawa powiązania danych kątowych (w wydaniach 1.x) otacza koncepcję pętli $digest i $scope. $scope to specjalny obiekt, który "samodzielnie śledzi" jego właściwości i tworzy detektor zdarzeń JavaScript dla każdej właściwości, używając metody $scope.$watch(). Te detektory monitorują zmiany elementów wejściowych zmienne w HTML i na właściwości $scope.

Za każdym razem, gdy uruchamiany jest dowolny detektor JavaScript, pętla $digest przechodzi przez każdy element pod numerem $watch i odpowiednio aktualizuje wartości. Możesz także zadzwonić pod numer $scope.$apply(), aby ręcznie wykonać pętlę $digest. Pętla ta może być uruchamiana wiele razy, ponieważ zmiany jednej wartości mogą wpływać na inną wartość pod numerem $watch, co powoduje uruchomienie kolejnego $digest. Pętla $digest ma zaślepkę iteracji, która zapewnia zatrzymanie na odwołaniach kołowych.

Pocieranie przychodzi, gdy mamy do czynienia z tablicami obiektów, a specjalna dyrektywa ng-repeat. Domyślnie funkcja $watch() sprawdza tylko równość odniesienia obiektu. W każdym z nich $digest AngularJS sprawdzi, czy nowe i stare wartości są tym samym "fizycznym" obiektem, i wywoła jego procedurę obsługi tylko wtedy, gdy faktycznie zmieni się obiekt odniesienia.

Aby temu przeciwdziałać, ng-repeat tworzy swój własny unikatowy scope. Pozwala to na unikalne $watch dla każdego elementu w tablicy. Wyzwanie polega na tym, że jeśli sama tablica ulegnie zmianie, to unikatowe scope zostanie zregenerowane wraz z wszystkimi elementami $watch. Przesuwanie, popping, łączenie tablic może spowodować powstanie wielu wartości $watch.

Angular oferuje kilka sposobów rozwiązania tego problemu.

Nowa składnia powiązania Raz w składni 1.3 pozwala słuchaczom istnieć tylko do momentu sprawdzenia wyrażenia. ng-repeat="element in ::elements" Powoduje iterację po tablicy, wypełnienie DOM, a następnie zniszczenie odbiornika zdarzeń. Jest to idealne rozwiązanie w sytuacjach, w których element DOM nie zmienia się po dokonaniu oceny.

Możliwe jest również agresywne śledzenie elementów za pomocą track by. ng-repeat="element in elements track by $id" utworzy wartość $watch na unikalnej wartości $id, a nie na pozycji elementu w tablicy. Pozwala to na bardziej stabilną propagację $watch i jest idealne w przypadkach, w których wartość elementu może się zmienić.

Co do tego, dlaczego zmiany dokonane w konsoli nie zostały utracone: Po pierwsze, zmiany w konsoli programisty nie będą wyzwalać żadnych detektorów zdarzeń. Po drugie, zmieniony specyficzny element DOM zostanie zmodyfikowany tylko wtedy, gdy $watch wykryje zmianę. Nie jest to jednak "Diff" kodu HTML; Angular nie "ogląda HTML", to jest "oglądanie danych", że tak powiem.

+0

Czuję, że powtarzałam się między tą odpowiedzią a odpowiedzią na http://stackoverflow.com/questions/29064684/memory-leak-in-ionicor-angular/29065924#29065924, ale nie mogę oprzeć się wrażeniu, że to jest złożony temat, który wymaga dokładnego wyjaśnienia. – Claies

+0

Dzięki za szczegółowe wyjaśnienie! Dzisiaj dowiedziałem się więcej o Angular, a także rozmawiałem z niektórymi ekspertami Angular, którzy powiedzieli to samo, o czym wspomniałeś w swojej odpowiedzi. Podsumowując różne odpowiedzi: logika renderowania 'ng-repeat' jest jednym z najbardziej zoptymalizowanych kodów w Angular i dlatego Angular nie tylko naiwnie oddaje cały element listy, kiedy coś modyfikuję. Jeśli istnieje wąskie gardło, to wąskim gardłem jest prawdopodobnie sama pętla trawienia - która przechodzi przez całą kolekcję przy każdej zmianie właściwości. Jednak może to być problem. – Zsolt

Powiązane problemy