Próbuję zrozumieć różnicę między ng-if
i 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ą?
Próbuję zrozumieć różnicę między ng-if
i 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ą?
Odpowiedzi:
Do ngIf
dyrektywa usuwa lub odtwarza część drzewa DOM w oparciu o wypowiedzi. Jeśli wyrażenie przypisane do ngIf
wartoś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 ngIf
jego zakresu, zostaje on zniszczony, a nowy element jest tworzony podczas przywracania elementu. Zakres utworzony w ramach ngIf
dziedziczy z zakresu nadrzędnego przy użyciu dziedziczenia prototypowego.
Jeśli ngModel
zostanie użyty w ngIf
celu 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 $parent
zmienna 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>
Do ngShow
dyrektywa Pokazuje lub ukrywa danego elementu HTML w oparciu o wypowiedzi przewidzianym do ngShow
atrybutu. Element jest pokazywany lub ukryty przez usunięcie lub dodanie ng-hide
klasy CSS do elementu. .ng-hide
Klasy CSS jest predefiniowane w angularjs i ustawia styl wyświetlania niepodważalna (przy użyciu !important
flagę).
<!-- 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 ngShow
wyrażenie ocenia, false
to ng-hide
klasa CSS jest dodawana do class
atrybutu elementu, powodując jego ukrywanie. Kiedy true
The ng-hide
klasa CSS jest usuwany z elementu powoduje element nie pojawiają się ukryte.
data.input
, działa on ... ale data
sam w modelu nie działa. @CodeHater
ngIf
tworzy nowy zakres, więc patrząc na powyższy przykład, zagnieżdżony ngModel
stworzyłby nowy data
model, 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. :)
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.
ng-if
Dyrektywa usuwa treści z strony i ng-show/ng-hide
używa CSS display
właściwość do ukrycia zawartości.
Jest to przydatne w przypadku, gdy chcesz użyć :first-child
i :last-child
selektorów pseudo do stylu.
:first-child
i i :last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
@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ł.
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-if
ponieważ 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, required
ale 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!
@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>
<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}}
Fakt, że ng-if
dyrektywa 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-click
zdarzenie, show
zmienna z zakresu wewnętrznego / wewnętrznego jest zmieniane, ale ng-if
obserwuje inną zmienną z zakresu zewnętrznego o tej samej nazwie, więc rozwiązanie nie działa. W przypadku ng-show
mamy tylko jedną show
zmienną, dlatego działa. Aby naprawić pierwszą próbę, powinniśmy odwoływać się do show
zakresu nadrzędnego / zewnętrznego przez $parent.show
.
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.
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.
ng-if tworzy zakres potomny, podczas gdy ng-show / ng-hide nie.
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.
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)
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
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. :)
ng-if
modelem dodanym przezng-model
już nie istnieje.