Jaka jest różnica między ng-if a ng-show / ng-hide

427

Próbuję zrozumieć różnicę między ng-ifi ng-show/ ng-hide, ale dla mnie wyglądają tak samo.

Czy jest jakaś różnica, o której powinienem pamiętać, wybierając jedną lub drugą?

Stephane Rolland
źródło

Odpowiedzi:

521

ngIf

Do ngIfdyrektywa usuwa lub odtwarza część drzewa DOM w oparciu o wypowiedzi. Jeśli wyrażenie przypisane do ngIfwartości fałszywej, element zostanie usunięty z DOM, w przeciwnym razie klon elementu zostanie ponownie wstawiony do DOM.

<!-- when $scope.myValue is truthy (element is restored) -->
<div ng-if="1"></div>

<!-- when $scope.myValue is falsy (element is removed) -->
<div ng-if="0"></div>

Gdy element jest usuwany przy użyciu ngIfjego zakresu, zostaje on zniszczony, a nowy element jest tworzony podczas przywracania elementu. Zakres utworzony w ramach ngIfdziedziczy z zakresu nadrzędnego przy użyciu dziedziczenia prototypowego.

Jeśli ngModelzostanie użyty w ngIfcelu powiązania z operacją podstawową JavaScript zdefiniowaną w zakresie nadrzędnym, wszelkie modyfikacje zmiennej w zakresie podrzędnym nie wpłyną na wartość w zakresie nadrzędnym, np.

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="data">
</div>        

Aby obejść tę sytuację i zaktualizować model w zakresie nadrzędnym z zakresu podrzędnego, użyj obiektu:

<input type="text" ng-model="data.input">
<div ng-if="true">
    <input type="text" ng-model="data.input">
</div>

Lub $parentzmienna odwołująca się do nadrzędnego obiektu zakresu:

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="$parent.data">
</div>

ngShow

Do ngShowdyrektywa Pokazuje lub ukrywa danego elementu HTML w oparciu o wypowiedzi przewidzianym do ngShowatrybutu. Element jest pokazywany lub ukryty przez usunięcie lub dodanie ng-hideklasy CSS do elementu. .ng-hideKlasy CSS jest predefiniowane w angularjs i ustawia styl wyświetlania niepodważalna (przy użyciu !importantflagę).

<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="1"></div>

<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="0" class="ng-hide"></div>

Kiedy ngShowwyrażenie ocenia, falseto ng-hideklasa CSS jest dodawana do classatrybutu elementu, powodując jego ukrywanie. Kiedy trueThe ng-hideklasa CSS jest usuwany z elementu powoduje element nie pojawiają się ukryte.

AlwaysALearner
źródło
31
Wskazówka: Usunięcie samego elementu HTML z ng-ifmodelem dodanym przez ng-modeljuż nie istnieje.
mrzmyr
3
@CodeHater Z powodzeniem wykorzystałem ng-if przez ng-show / ng-hide na stronie, która w innym przypadku miałaby dużą domenę. Wydawało się, że strona wydaje się szybsza, ale w żadnym wypadku nie jest to analiza naukowa.
Ed Spencer
Problem z pełnym zrozumieniem polega na tym, jak / dlaczego, gdy masz obiekt w modelu data.input, działa on ... ale datasam w modelu nie działa. @CodeHater
Mark Pieszak - Trilon.io
7
@mcpDESIGNS ngIftworzy nowy zakres, więc patrząc na powyższy przykład, zagnieżdżony ngModelstworzyłby nowy datamodel, nawet jeśli model o tej samej nazwie istnieje w zakresie nadrzędnym. Ale kiedy używasz notacji kropkowej, sprawiasz, że JS sprawdza łańcuch prototypów zakresu. Jeśli więc nie znajdzie wartości w bieżącym zakresie, spróbuje poszukać jej w zakresie nadrzędnym i tak dalej. Kilka innych dyrektyw, które tworzą inny zakres to ngInclude, ngRepeat. Mam nadzieję, że teraz wszystko jest jasne. :)
AlwaysALearner,
3
Który z nich jest lepszy pod względem wydajności? Myślę, że ng-show i ng-hide, prawda?
tom10271,
97

Być może ciekawym punktem do zrobienia jest różnica między priorytetami między nimi.

O ile mogę stwierdzić, dyrektywa ng-if ma jeden z najwyższych (jeśli nie najwyższy) priorytet wszystkich dyrektyw Angular. Co oznacza: będzie działał PIERWSZY przed wszystkimi innymi dyrektywami o niższym priorytecie. Fakt, że działa PIERWSZY, oznacza, że ​​element jest skutecznie usuwany przed przetworzeniem jakichkolwiek wewnętrznych dyrektyw. A przynajmniej: co z tego robię.

Obserwowałem i użyłem tego w interfejsie użytkownika, który buduję dla mojego obecnego klienta. Cały interfejs użytkownika jest dość mocno zapakowany, a na nim było ng-show i ng-hide. Nie wchodząc w zbyt wiele szczegółów, ale zbudowałem ogólny komponent, którym można zarządzać za pomocą konfiguracji JSON, więc musiałem dokonać pewnych zmian w szablonie. Występuje powtórzenie ng, a wewnątrz powtórzenia ng pokazana jest tabela, która zawiera wiele pokazów ng, ukrywania ng, a nawet przełączników ng. Chcieli wyświetlić co najmniej 50 powtórzeń na liście, co skutkowałoby rozwiązaniem mniej więcej 1500-2000 dyrektyw. Sprawdziłem kod, a backend Java + niestandardowe JS z przodu zajęłoby około 150 ms na przetworzenie danych, a następnie Angular przeżułby na nim jakieś 2-3 sekundy przed wyświetleniem. Klient nie narzekał, ale byłem przerażony :-)

Podczas poszukiwań natknąłem się na dyrektywę ng-if. Być może najlepiej wskazać, że w momencie tworzenia tego interfejsu użytkownika nie było dostępnego ng-jeśli jest dostępny. Ponieważ ng-show i ng-hide miały w sobie funkcje, które zwracały logiczne wartości, mogłem z łatwością zastąpić je wszystkie ng-if. W ten sposób wydaje się, że wszystkie wewnętrzne dyrektywy nie są już oceniane. Oznaczało to, że wróciłem do około jednej trzeciej wszystkich ocenianych dyrektyw, a zatem interfejs użytkownika przyspieszył do około 500 ms - 1 s czasu ładowania. (Nie mam możliwości ustalenia dokładnych sekund)

Uwaga: fakt, że dyrektywy nie są oceniane, jest pouczającym domysłem na temat tego, co dzieje się poniżej.

Tak więc, moim zdaniem: jeśli chcesz, aby element był obecny na stronie (tzn. Do sprawdzania elementu, czy cokolwiek innego), ale po prostu się ukrył, użyj ng-show / ng-hide. We wszystkich innych przypadkach użyj ng-if.

gjori
źródło
1
Tak, myślę, że jest to celem ng-if: skrócenie czasu przetwarzania. Ta dyrektywa istnieje na pewno nie tylko z powodu niektórych pseudoselektorów CSS. Dobry post! +1
Bartłomiej Zalewski
16

@EdSpencer jest poprawny. Jeśli masz wiele elementów i używasz ng-if tylko do tworzenia odpowiednich, oszczędzasz zasoby. @CodeHater jest również nieco poprawny, jeśli zamierzasz bardzo często usuwać i pokazywać element, ukrywanie go zamiast usuwania może poprawić wydajność.

Główny przypadek użycia, który znajduję dla ng-if, polega na tym, że pozwala mi to na czystą walidację i usunięcie elementu, jeśli zawartość jest nielegalna. Na przykład mógłbym odwoływać się do zmiennej o pustym obrazie, która wygeneruje błąd, ale jeśli sprawdzę, czy jest pusta, wszystko będzie dobrze. Gdybym zrobił ng-show, błąd nadal by się pojawił.

AturSams
źródło
7

Jedną ważną rzeczą, o której należy pamiętać w przypadku ng-if i ng-show, jest to, że podczas korzystania z kontrolek formularzy lepiej jest używać, ng-ifponieważ całkowicie usuwa element z domeny.

Ta różnica jest ważna, ponieważ jeśli utworzysz pole wejściowe za pomocą, required="true"a następnie skonfigurujesz ng-show="false"je jako ukryte, Chrome zgłasza następujący błąd, gdy użytkownik próbuje przesłać formularz:

An invalid form control with name='' is not focusable.

Powodem jest to, że pole wejściowe jest obecne i jest, requiredale ponieważ jest ukryte, Chrome nie może się na nim skupić. Może to dosłownie zepsuć kod, ponieważ błąd ten zatrzymuje wykonywanie skryptu. Więc uważaj!

supersan
źródło
To jest prawdziwy fakt, jeśli używasz kontrolek formularza do sprawdzania poprawności, wtedy będziesz bardzo cierpieć, jeśli użyjesz ng-show / ng-hide. A jeśli masz wiele sekcji ukrytych / pokazanych na podstawie wyrażenia. Więc jeśli użyjesz ng-show / hide, elementy będą tam nadal, a sprawdzanie poprawności nie powiedzie się, mimo że nie są wyświetlane na ekranie. więc ng-if cię uratuje :)
NeverGiveUp161 17.08.18
5

@Gajus Kuizinas i @CodeHater są poprawne. Oto tylko przykład. Podczas pracy z ng-if, jeśli przypisana wartość to false, wówczas wszystkie elementy HTML zostaną usunięte z DOM. a jeśli przypisana wartość jest prawdą, wówczas elementy HTML będą widoczne w DOM. Zakres będzie inny w porównaniu z zakresem nadrzędnym. Ale w przypadku ng-show po prostu pokaże i ukryje elementy na podstawie przypisanej wartości. Ale zawsze pozostaje w DOM. Zmienia się tylko widoczność zgodnie z przypisaną wartością.

http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview

Mam nadzieję, że ten przykład pomoże ci zrozumieć zakresy. Spróbuj podać fałszywe wartości dla ng-show i ng-if i sprawdź DOM w konsoli. Spróbuj wprowadzić wartości w polach wprowadzania i obserwuj różnicę.

<!DOCTYPE html>

Cześć Plunker!

<input type="text" ng-model="data">
<div ng-show="true">
    <br/>ng-show=true :: <br/><input type="text" ng-model="data">
</div>
<div ng-if="true">
    <br/>ng-if=true :: <br/><input type="text" ng-model="data">
</div> 
{{data}}


źródło
2

Fakt, że ng-ifdyrektywa ta, w przeciwieństwie do tego ng-show, ma swój własny zakres, prowadzi do interesującej praktycznej różnicy:

angular.module('app', []).controller('ctrl', function($scope){
  $scope.delete = function(array, item){
    array.splice(array.indexOf(item), 1);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app='app' ng-controller='ctrl'>
   <h4>ng-if:</h4>
   <ul ng-init='arr1 = [1,2,3]'>
      <li ng-repeat='x in arr1'>
        {{show}}
        <button ng-if='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-if='show' ng-click='delete(arr1, x)'>Yes {{show}}</button>
        <button ng-if='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-show:</h4>
   <ul ng-init='arr2 = [1,2,3]'>
      <li ng-repeat='x in arr2'>
        {{show}}
        <button ng-show='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-show='show' ng-click='delete(arr2, x)'>Yes {{show}}</button>
        <button ng-show='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-if with $parent:</h4>
    <ul ng-init='arr3 = [1,2,3]'>
      <li ng-repeat='item in arr3'>
        {{show}}
        <button ng-if='!show' ng-click='$parent.show=!$parent.show'>Delete {{$parent.show}}</button>
        <button ng-if='show' ng-click='delete(arr3, x)'>Yes {{$parent.show}}</button>
        <button ng-if='show' ng-click='$parent.show=!$parent.show'>No</button>
      </li>
   </ul>
</div>

Na pierwszej liście on-clickzdarzenie, showzmienna z zakresu wewnętrznego / wewnętrznego jest zmieniane, ale ng-ifobserwuje inną zmienną z zakresu zewnętrznego o tej samej nazwie, więc rozwiązanie nie działa. W przypadku ng-showmamy tylko jedną showzmienną, dlatego działa. Aby naprawić pierwszą próbę, powinniśmy odwoływać się do showzakresu nadrzędnego / zewnętrznego przez $parent.show.

Slava Utesinov
źródło
1
  1. ng-if jeśli false usunie elementy z DOM. Oznacza to, że wszystkie wydarzenia, dyrektywy dołączone do tych elementów zostaną utracone. Na przykład, kliknij ng na jeden z elementów potomnych, gdy ng-if ma wartość false, element ten zostanie usunięty z DOM i ponownie, gdy to prawda, zostanie odtworzony.

  2. ng-show / ng-hide nie usuwa elementów z DOM. Wykorzystuje style CSS (.ng-hide) do ukrywania / pokazywania elementów. W ten sposób twoje wydarzenia, dyrektywy dołączone do dzieci nie zostaną utracone.

  3. ng-if tworzy zakres potomny, podczas gdy ng-show / ng-hide nie.

Amay Kulkarni
źródło
1

ng-show i ng-hide działają w odwrotny sposób. Ale różnica między ng-hide lub ng-show z ng-if polega na tym, że jeśli użyjemy ng-if, wówczas element zostanie utworzony w domenie, ale z ng-hide / ng-show element zostanie całkowicie ukryty.

ng-show=true/ng-hide=false:
Element will be displayed

ng-show=false/ng-hide=true:
element will be hidden

ng-if =true
element will be created

ng-if= false
element will be created in the dom. 
użytkownik1001
źródło
0

Należy zauważyć, że coś, co mi się teraz przydarzyło: ng-show ukrywa zawartość za pomocą css, tak, ale spowodowało dziwne usterki w div, które powinny być przyciskami.

Miałem kartę z dwoma przyciskami na dole i w zależności od aktualnego stanu jeden jest wymieniany na trzeci przykładowy przycisk edycji z nowym wpisem. Używając ng-show = false, aby ukryć lewy (obecny jako pierwszy w pliku), zdarzyło się, że następujący przycisk skończył z prawą ramką na zewnątrz karty. ng-if naprawia to, nie włączając w ogóle kodu. (Sprawdziłem tutaj, czy są jakieś ukryte niespodzianki przy użyciu ng-if zamiast ng-show)

helius
źródło
0

ngIf dokonuje manipulacji na DOM poprzez usunięcie lub odtworzenie elementu.

Podczas gdy ngShow stosuje reguły css do ukrywania / pokazywania rzeczy.

W większości przypadków (nie zawsze) podsumowałbym to tak: jeśli potrzebujesz jednorazowego sprawdzenia, aby pokazać / ukryć rzeczy, użyj ng-if, jeśli chcesz pokazać / ukryć rzeczy na podstawie działań użytkownika na ekranie (np. Zaznaczone pole wyboru, a następnie pokaż pole tekstowe, odznaczone, a następnie ukryj pole tekstowe itp.), a następnie użyjng-show

ciekawy Chłopak
źródło
-17

Jedną interesującą różnicą w ng-if i ng-show jest:

BEZPIECZEŃSTWO

Elementy DOM obecne w bloku ng-if nie będą renderowane, jeśli jego wartość będzie fałszywa

gdzie tak jak w przypadku ng-show, użytkownik może otworzyć okno Inspect Element i ustawić jego wartość na TRUE.

A z okrzykiem wyświetla się cała zawartość, która miała być ukryta, co stanowi naruszenie bezpieczeństwa. :)

Ashish_B
źródło
27
To wyjątkowo słaba forma bezpieczeństwa. Jeśli treść jest przekazywana klientowi przez serwer, musisz założyć, że użytkownik / atakujący może uzyskać do niego dostęp, niezależnie od tego, czy jest on obecny w DOM. Serwer musi wymuszać całą logikę autoryzacji.
tlrobinson
Pomyśl o html zamiast jsp ... teraz, jeśli chcesz wymusić bezpieczeństwo na komponentach html ... np. jeśli chcesz ukryć niektóre komponenty przed użytkownikiem ... jak to osiągniesz. A co, jeśli twoja konfiguracja jest podzielona na stronę serwera dla zaplecza i stronę klienta dla interfejsu?
Ashish_B