Kiedy faworyzować ng-if kontra ng-show / ng-hide?

516

Rozumiem to ng-showi ng-hidewpływam na klasę ustawioną na elemencie, która ng-ifkontroluje, czy element jest renderowany jako część DOM.

Czy istnieją wytyczne dotyczące wybierania opcji ng-ifpowyżej ng-show/ ng-hidelub odwrotnie?

Patrice Chalin
źródło
1
Nie dotyczy języka strzałki .
naXa

Odpowiedzi:

703

Zależy od przypadku użycia, ale podsumowując różnicę:

  1. ng-ifusunie elementy z DOM. Oznacza to, że wszystkie twoje programy obsługi lub cokolwiek innego związane z tymi elementami zostaną utracone. Na przykład, jeśli powiążesz moduł obsługi kliknięć z jednym z elementów potomnych, gdy zostanie ng-ifoceniony wartość false, element ten zostanie usunięty z DOM, a twój moduł obsługi kliknięć nie będzie działał, nawet po ng-ifpóźniejszym sprawdzeniu wartości true i wyświetleniu elementu. Będziesz musiał ponownie podłączyć program obsługi.
  2. ng-show/ng-hidenie usuwa elementów z DOM. Wykorzystuje style CSS do ukrywania / pokazywania elementów (uwaga: może być konieczne dodanie własnych klas). W ten sposób przewodnicy, którzy byli przywiązani do dzieci, nie zostaną utraceni.
  3. ng-iftworzy zakres potomny, podczas gdy ng-show/ng-hidenie

Elementy, które nie znajdują się w DOM, mają mniejszy wpływ na wydajność, a Twoja aplikacja internetowa może wydawać się szybsza w użyciu w ng-ifporównaniu do ng-show/ng-hide. Z mojego doświadczenia wynika, że ​​różnica jest znikoma. Animacje są możliwe przy użyciu obu ng-show/ng-hidei ng-ifwraz z przykładami dla obu w dokumentacji Angular.

Ostatecznie pytanie, na które musisz odpowiedzieć, brzmi: czy możesz usunąć element z DOM, czy nie?

markovuksanovic
źródło
19
Możesz używać animacji CSS3 z ng-if. Sprawdź akapit Animacje i przykład w dokumentacji . Również z ng-hide/ng-showselektorami css lubią :first-childlub :nth-childnie będą działać poprawnie, ponieważ ukryte elementy również zostaną policzone.
Łukasz Wojciechowski
4
Usługa animacji w angular.dart jest stosunkowo nowa. W chwili pisania tego nie było dostępne.
markovuksanovic
44
Pierwszy punkt nie stanowi problemu, jeśli używasz dyrektyw (takich jak ng-click) do wiązania programów obsługi, tak jak powinieneś.
Kevin C.
9
Ponadto ng-iftworzy nowy zakres, podczas gdy ng-shownie.
martin
8
Należy również wspomnieć, że dodawanie i usuwanie elementów z DOM może powodować wysokie koszty wydajności, jeśli jest to wykonywane często.
Kevin C.
130

Zobacz tutaj CodePen, który pokazuje różnicę w działaniu ng-if / ng-show w DOM.

@markovuksanovic dobrze odpowiedział na pytanie. Ale ja się na to z innej perspektywy: Chciałbym zawsze używać ng-ifi dostać te elementy z DOM, chyba że:

  1. z jakiegoś powodu potrzebujesz powiązań danych i $watch-es na swoich elementach, aby pozostały aktywne, dopóki są niewidoczne. Formularze mogą być dobrym przykładem, jeśli chcesz mieć możliwość sprawdzenia poprawności na wejściach, które nie są obecnie widoczne, w celu ustalenia, czy cały formularz jest prawidłowy.
  2. Używasz naprawdę dopracowanej logiki stanowej z funkcjami obsługi zdarzeń warunkowych, jak wspomniano powyżej. To powiedziawszy , jeśli okaże się, że ręcznie dołączasz i odłączasz procedury obsługi, tak że tracisz ważny stan podczas korzystania z ng-if, zadaj sobie pytanie, czy stan ten byłby lepiej reprezentowany w modelu danych, a procedury obsługi stosowane warunkowo przez dyrektywy za każdym razem element jest renderowany. Innymi słowy, obecność / brak programów obsługi jest formą danych stanu. Pobierz te dane z modelu DOM i do modelu. Obecność / brak programów obsługi powinny być określone przez dane, a zatem łatwe do odtworzenia.

Angular jest napisany naprawdę dobrze. Jest szybki, biorąc pod uwagę, co robi. Ale to, co robi, to cała magia, która sprawia, że ​​trudne rzeczy (takie jak dwukierunkowe wiązanie danych) wyglądają banalnie łatwo. Sprawienie, by wszystkie te rzeczy wyglądały na łatwe, wiąże się z pewnym nakładem wydajności. Możesz być zszokowany, gdy zorientujesz się, ile setek lub tysięcy razy funkcja setera jest oceniana podczas $digestcyklu na kawałku DOM, na który nikt nawet nie patrzy. I wtedy zdajesz sobie sprawę, że masz dziesiątki lub setki niewidzialnych elementów, które robią to samo ...

Komputery stacjonarne mogą rzeczywiście być wystarczająco mocne, aby większość problemów z szybkością wykonywania JS była dyskusyjna. Ale jeśli pracujesz na urządzenia mobilne, używanie ng-if, gdy tylko jest to możliwe, powinno być proste. Szybkość JS nadal ma znaczenie dla procesorów mobilnych. Używanie ng-if jest bardzo łatwym sposobem na uzyskanie potencjalnie znaczącej optymalizacji przy bardzo, bardzo niskich kosztach.

XML
źródło
6
Bardzo fajny dodatek do powyższej odpowiedzi. Biorąc pod uwagę dobry kontekst, który również pomaga w podejmowaniu decyzji. Dzięki.
Sean
1
ng-showmoże być przydatna, gdy masz, powiedzmy, że każda z kart zawiera dużo treści, których renderowanie zajmuje dużo czasu. Po pierwszym renderowaniu przechodzenie między kartami będzie natychmiastowe, natomiast ng-ifwymagałoby ponownego renderowania, wiązania zdarzeń itp. Minusem, jak mówisz, jest tworzenie zegarków wykonujących się w tle. Angular rozpaczliwie potrzebujeng-ifshowwatch
najlepiej
53

Z mojego doświadczenia:

1) Jeśli twoja strona ma przełącznik, który używa ng-if / ng-show do pokazywania / ukrywania czegoś, ng-if powoduje większe opóźnienie przeglądarki (wolniej). Na przykład: jeśli masz przycisk służący do przełączania między dwoma widokami, ng-show wydaje się być szybszy.

2) ng-if utworzy / zniszczy zakres, gdy zostanie oceniony jako prawda / fałsz. Jeśli masz kontroler podłączony do ng-if, ten kod kontrolera będzie wykonywany za każdym razem, gdy ng-if zostanie ocenione jako prawda. Jeśli używasz ng-show, kod kontrolera zostanie wykonany tylko raz. Więc jeśli masz przycisk, który przełącza między wieloma widokami, użycie ng-if i ng-show miałoby ogromną różnicę w sposobie pisania kodu kontrolera.

Yi Z
źródło
5
To ogromna prawda! ng-if niekoniecznie przyspiesza twój frontend. To zależy od twoich potrzeb. W rzeczywistości może być odwrotnie, jeśli używasz w niewłaściwej sytuacji.
Thiago C. S Ventura
1
Ale według mnie jako ng-if nie renderuje się w DOM, więc jest szybki w porównaniu do ng-show / hide. czy się mylę proszę pozwól mi poprawić w tym momencie.
Pardeep Jain
1
ng-if byłoby szybsze, gdyby miał wartość false, ponieważ, jak mówisz, nic nie musi być wstawiane do DOM. Ale jeśli to prawda, masz narzut związany z wstawieniem - być może dość skomplikowanego - elementu do DOM.
Mawg mówi o przywróceniu Moniki
„2) ng-if utworzy / zniszczy zakres, gdy zostanie oceniony jako prawda / fałsz. Jeśli masz kontroler podłączony do ng-if, ten kod kontrolera będzie wykonywany za każdym razem”
The Red Pea
35

Odpowiedź nie jest prosta:

To zależy od komputerów docelowych (mobilne vs stacjonarne), zależy od charakteru twoich danych, przeglądarki, systemu operacyjnego, sprzętu, na którym działa ... będziesz musiał przeprowadzić testy porównawcze, jeśli naprawdę chcesz wiedzieć.

Jest to głównie problem z pamięcią a obliczeniami ... ponieważ w przypadku większości problemów z wydajnością różnica może stać się znacząca w przypadku powtarzających się elementów (n), takich jak listy, szczególnie gdy są zagnieżdżone (nxn lub gorzej), a także rodzaj obliczeń wykonywanych w tych elementach :

  • ng-show : Jeśli te opcjonalne elementy są często obecne (gęste), jak powiedzmy w 90% przypadków, może być szybsze ich przygotowanie i pokazywanie / ukrywanie, szczególnie jeśli ich zawartość jest tania (zwykły tekst, nic obliczać lub ładować). To zużywa pamięć, ponieważ wypełnia DOM ukrytymi elementami, ale po prostu pokaż / ukryj coś, co już istnieje, może być tanią operacją dla przeglądarki.

  • ng-if : Jeśli przeciwnie, elementy raczej nie zostaną pokazane (rzadkie), po prostu je zbuduj i zniszcz w czasie rzeczywistym, szczególnie jeśli ich zawartość jest kosztowna (obliczenia / sortowane / filtrowane, obrazy, generowane obrazy). Jest to idealne rozwiązanie dla rzadkich lub „na żądanie” elementów, oszczędza pamięć pod względem niewypełniania DOM, ale może kosztować dużo obliczeń (tworzenie / niszczenie elementów) i przepustowości (uzyskiwanie zdalnej zawartości). Zależy to również od tego, ile obliczasz w widoku (filtrowanie / sortowanie) w porównaniu z tym, co już masz w modelu (dane wstępnie posortowane / wstępnie odfiltrowane).

Christophe Roussy
źródło
2
Inne odpowiedzi dotyczące faktów technicznych. Ten dla mądrości. Wyraźnie zbudowałeś nietrywialne aplikacje Angular, proszę pana! +1
najdalej
Ten problem wykracza poza granice, jest podstawowym problemem w informatyce, istnieje punkt, z którego jedna metoda jest bardziej wydajna niż druga. Zwykle można to znaleźć poprzez pewne testy porównawcze. Więc możesz nawet przełączać się między metodami w zależności od liczby przedmiotów ... Podobny temat: math.stackexchange.com/questions/1632739/…
Christophe Roussy
12

Jedna ważna uwaga:

ngIf (w przeciwieństwie do ngShow) zwykle tworzy zakresy potomne, które mogą dawać nieoczekiwane wyniki.

Miałem z tym problem i spędziłem DUŻO czasu, aby dowiedzieć się, co się dzieje.

(Moja dyrektywa zapisywała wartości modelu w niewłaściwym zakresie).

Aby zaoszczędzić włosy, użyj ngShow, chyba że biegniesz zbyt wolno.

Różnica w wydajności i tak jest ledwo zauważalna i nie jestem jeszcze pewien, kto jest na korzyść bez testu ...

użytkownik2173353
źródło
8
Używanie $parent.scopevarw powiązaniach danych w ngIf rozwiąże takie problemy, jak problemy z zasięgami potomnymi podczas używania ngIf
meconroy
2
Nie jest to do końca prawdą (tzn. Oryginalny komentarz @ user2173353). Jeśli będziesz przestrzegać dobrych praktyk, nie będziesz miał kłopotów. To dość podstawowa zasada: „jeśli nie ma kropki, robisz to źle”. Zobacz tutaj, jak to działa: bit.ly/1SPv4wL . Kolejne świetne odniesienie (patrz błąd nr 2): bit.ly/1QfFeWd > (Moja dyrektywa zapisywała wartości swojego modelu w niewłaściwym zakresie). Jest to wynik nieprzestrzegania powyższej praktyki.
piotr.d
1
@ piotr.d Masz rację, ale nie jest to coś, na czym początkujący może się skupić, i jest inna najlepsza praktyka, która mówi, że lepiej pozostawić poprawę wydajności na koniec (szczególnie ulepszenia wydajności, które mogą nie być poprawą w rzeczywistości ). Widziałem ludzi, którzy ngIfwszędzie wierzyli, że poprawi to wydajność. To po prostu nieprawda i nie można powiedzieć, który jest najlepszy, ngIflub ngShowbez testu lub głębokiej analizy w konkretnym przypadku. Dlatego nadal zalecam zapominanie ngIf, dopóki nie zobaczy się złej wydajności lub nie wie, co robi
user2173353
2
Słuszna uwaga. Ale użycie kontroleraAs sprawia, że ​​nie stanowi to problemu. Zobacz na przykład podejście Johna Papy do kontroleraAs i vm .
jsruok
4

ng-jeśli na ng-include i na ng-kontrolerze będą miały duży wpływ na ng-include, to nie załaduje wymaganej części i nie będzie przetwarzać, chyba że flaga jest prawdziwa na ng-kontrolerze, nie załaduje kontrolera, chyba że flaga jest prawda, ale problem polega na tym, że gdy flaga zostanie sfałszowana w ng - jeśli usunie się z DOM, gdy flaga wróci do stanu rzeczywistego, przeładuje DOM w tym przypadku ng-show jest lepszy, raz pokaże ng-jeśli jest lepszy

Saad Ahmed
źródło
4

Jeśli użyjesz ng-show or ng-hide z treści (np. Miniatury z serwera) zostaną załadowane niezależnie od wartości wyrażenia, ale będą wyświetlane na podstawie wartości wyrażenia.

Jeśli użyjesz, ng-ifzawartość zostanie załadowana tylko wtedy, gdy wyrażenie ng-if będzie zgodne z prawdą.

Używanie ng-if jest dobrym pomysłem w sytuacji, gdy zamierzasz załadować dane lub obrazy z serwera i wyświetlać je tylko w zależności od interakcji użytkowników. W ten sposób ładowanie strony nie będzie blokowane przez niepotrzebne nowe zadania.

appdroid
źródło
Jest to szczególnie przydatne, ponieważ większość przeglądarek ładuje obrazy, nawet jeśli CSS ukrywa swoje kontenery DOM. Zwykle szukają tylko srcatrybutu imgtagu, gdy jest on załadowany!
Christophe Roussy,