Was ist der Unterschied zwischen ng-if und ng-show / ng-hide

427

Ich versuche den Unterschied zwischen ng-ifund ng-show/ zu verstehen ng-hide, aber sie sehen für mich gleich aus.

Gibt es einen Unterschied, den ich beachten sollte, wenn ich mich für den einen oder anderen entscheide?

Stephane Rolland
quelle

Antworten:

521

ngIf

Die ngIfDirektive entfernt oder erstellt einen Teil des DOM-Baums basierend auf einem Ausdruck neu. Wenn der Ausdruck, der zugewiesen wird, ngIfeinen falschen Wert ergibt, wird das Element aus dem DOM entfernt, andernfalls wird ein Klon des Elements erneut in das DOM eingefügt.

<!-- 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>

Wenn ein Element mithilfe ngIfseines Bereichs entfernt wird, wird es zerstört und ein neuer Bereich wird erstellt, wenn das Element wiederhergestellt wird. Der innerhalb ngIfvon erstellte Bereich erbt mithilfe der prototypischen Vererbung von seinem übergeordneten Bereich.

Wenn ngModelinnerhalb verwendet wird ngIf, um an ein im übergeordneten Bereich definiertes JavaScript-Grundelement zu binden, wirken sich Änderungen an der Variablen im untergeordneten Bereich nicht auf den Wert im übergeordneten Bereich aus, z

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

Verwenden Sie ein Objekt, um diese Situation zu umgehen und das Modell im übergeordneten Bereich innerhalb des untergeordneten Bereichs zu aktualisieren:

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

Oder $parentVariable, um auf das übergeordnete Bereichsobjekt zu verweisen:

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

ngShow

Die ngShowDirektive zeigt oder verbirgt das angegebene HTML-Element basierend auf dem Ausdruck, der für das ngShowAttribut bereitgestellt wird. Das Element wird angezeigt oder ausgeblendet, indem die ng-hideCSS-Klasse entfernt oder dem Element hinzugefügt wird. Die .ng-hideCSS-Klasse ist in AngularJS vordefiniert und setzt den Anzeigestil auf none (mithilfe eines !importantFlags).

<!-- 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>

Wenn der ngShowAusdruck ausgewertet wird, falsewird die ng-hideCSS-Klasse dem classAttribut des Elements hinzugefügt, wodurch es ausgeblendet wird. Wenn truedie ng-hideCSS-Klasse aus dem Element entfernt wird, wird das Element nicht ausgeblendet angezeigt.

AlwaysALearner
quelle
31
Hinweis: Durch Entfernen des HTML-Elements selbst mit ng-ifdem Modell, das von hinzugefügt wurde ng-model, ist es nicht mehr vorhanden.
Mrzmyr
3
@CodeHater Ich habe ng-if erfolgreich über ng-show / ng-hide auf einer Seite eingesetzt, die sonst einen großen Dom gehabt hätte. Es schien die Seite zu machen fühlen schneller, ist aber keineswegs die wissenschaftliche Analyse.
Ed Spencer
Der Teil, bei dem ich Probleme habe, vollständig zu verstehen, ist, wie / warum, wenn Sie ein Objekt im Modell haben, data.inputes funktioniert ... aber dataallein im Modell funktioniert es nicht. @ CodeHater
Mark Pieszak - Trilon.io
7
@mcpDESIGNS ngIferstellt einen neuen Bereich. Wenn Sie also das obige Beispiel über dem verschachtelten betrachten ngModel, wird ein neues dataModell erstellt, obwohl im übergeordneten Bereich ein Modell mit demselben Namen vorhanden ist. Wenn Sie jedoch eine Punktnotation verwenden, lässt JS die Prototypenkette des Oszilloskops nachschlagen. Wenn der Wert im aktuellen Bereich nicht gefunden wird, wird versucht, ihn im übergeordneten Bereich usw. zu suchen. Nur wenige andere Richtlinien, die einen anderen Geltungsbereich schaffen, sind ngInclude, ngRepeat. Hoffe es ist jetzt klar. :)
AlwaysALearner
3
Welches ist besser für die Leistung? Ich denke, ng-show und ng-hide, nicht wahr?
Tom10271
97

Vielleicht ist ein interessanter Punkt der Unterschied zwischen den Prioritäten zwischen beiden.

Soweit ich das beurteilen kann, hat die ng-if-Direktive eine der höchsten (wenn nicht die höchste) Priorität aller Angular-Direktiven. Das heißt: Es wird ZUERST vor allen anderen Direktiven mit niedrigerer Priorität ausgeführt. Die Tatsache, dass es ZUERST ausgeführt wird, bedeutet, dass das Element effektiv entfernt wird, bevor innere Anweisungen verarbeitet werden. Oder zumindest: das mache ich daraus.

Ich habe dies beobachtet und in der Benutzeroberfläche verwendet, die ich für meinen aktuellen Kunden erstelle. Die gesamte Benutzeroberfläche ist ziemlich voll und es gab überall ng-show und ng-hide. Um nicht zu sehr ins Detail zu gehen, habe ich eine generische Komponente erstellt, die mit der JSON-Konfiguration verwaltet werden kann, sodass ich einige Änderungen in der Vorlage vornehmen musste. Es ist eine ng-Wiederholung vorhanden, und innerhalb der ng-Wiederholung wird eine Tabelle angezeigt, in der viele ng-Shows, ng-Häute und sogar ng-Schalter vorhanden sind. Sie wollten mindestens 50 Wiederholungen in der Liste anzeigen, was dazu führen würde, dass mehr oder weniger 1500-2000 Anweisungen gelöst werden müssten. Ich habe den Code überprüft, und das Java-Backend + benutzerdefiniertes JS auf der Vorderseite würde ungefähr 150 ms dauern, um die Daten zu verarbeiten, und dann würde Angular 2-3 Sekunden darauf kauen, bevor es angezeigt wird. Der Kunde hat sich nicht beschwert, aber ich war entsetzt :-)

Bei meiner Suche bin ich auf die ng-if-Direktive gestoßen. Nun ist es vielleicht am besten darauf hinzuweisen, dass zum Zeitpunkt der Konzeption dieser Benutzeroberfläche kein ng-if verfügbar war. Da ng-show und ng-hide Funktionen enthielten, die Boolesche Werte zurückgaben, konnte ich sie alle leicht durch ng-if ersetzen. Auf diese Weise schienen nicht alle inneren Richtlinien mehr bewertet zu werden. Das bedeutete, dass ich auf ungefähr ein Drittel aller evaluierten Direktiven zurückfiel und die Benutzeroberfläche auf ungefähr 500 ms beschleunigte - 1 Sekunde Ladezeit. (Ich habe keine Möglichkeit, genaue Sekunden zu bestimmen)

Beachten Sie: Die Tatsache, dass die Richtlinien nicht bewertet werden, ist eine fundierte Vermutung darüber, was darunter geschieht.

Meiner Meinung nach: Wenn das Element auf der Seite vorhanden sein muss (dh zum Überprüfen des Elements oder was auch immer), aber einfach ausgeblendet werden soll, verwenden Sie ng-show / ng-hide. In allen anderen Fällen verwenden Sie ng-if.

gjoris
quelle
1
Ja, ich denke, dies ist das Ziel von ng-if: die Verarbeitungszeit zu verkürzen. Diese Direktive existiert sicher nicht nur aufgrund einiger CSS-Pseudoselektoren. Guter Post! +1
Bartłomiej Zalewski
16

@ EdSpencer ist korrekt. Wenn Sie viele Elemente haben und ng-if verwenden, um nur die relevanten zu instanziieren, sparen Sie Ressourcen. @CodeHater ist auch etwas korrekt, wenn Sie ein Element sehr oft entfernen und anzeigen möchten. Wenn Sie es ausblenden, anstatt es zu entfernen, kann dies die Leistung verbessern.

Der Hauptanwendungsfall, den ich für ng-if finde, ist, dass ich damit ein Element sauber validieren und entfernen kann, wenn der Inhalt illegal ist. Zum Beispiel könnte ich auf eine Variable für den Nullbildnamen verweisen, und das wird einen Fehler auslösen, aber wenn ich ng-if und prüfe, ob es null ist, ist alles gut. Wenn ich eine ng-Show machen würde, würde der Fehler immer noch ausgelöst.

AturSams
quelle
7

Eine wichtige Sache, die Sie bei ng-if und ng-show beachten sollten, ist, dass die Verwendung von Formularsteuerelementen besser ist, ng-ifda das Element vollständig aus dem Dom entfernt wird.

Dieser Unterschied ist wichtig, denn wenn Sie ein Eingabefeld mit erstellen required="true"und dann festlegen ng-show="false", dass es ausgeblendet wird, gibt Chrome den folgenden Fehler aus, wenn der Benutzer versucht, das Formular zu senden:

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

Der Grund dafür ist, dass das Eingabefeld vorhanden ist und es ist, requiredaber da es versteckt ist, kann sich Chrome nicht darauf konzentrieren. Dies kann Ihren Code buchstäblich beschädigen, da dieser Fehler die Skriptausführung anhält. Also sei vorsichtig!

Supersan
quelle
Dies ist die wahre Tatsache, wenn Sie Formularsteuerelemente zur Validierung verwenden, werden Sie viel leiden, wenn Sie ng-show / ng-hide verwenden. Und wenn Sie mehrere Abschnitte ausgeblendet / angezeigt haben, basierend auf dem Ausdruck. Wenn Sie also ng-show / hide verwenden, sind die Elemente weiterhin vorhanden und die Validierung schlägt fehl, obwohl sie nicht auf dem Bildschirm angezeigt werden. also ng-if rette dich :)
NeverGiveUp161
5

@Gajus Kuizinas und @CodeHater sind korrekt. Hier gebe ich nur ein Beispiel. Während wir mit ng-if arbeiten und der zugewiesene Wert falsch ist, werden die gesamten HTML-Elemente aus dem DOM entfernt. Wenn der zugewiesene Wert true ist, werden die HTML-Elemente im DOM angezeigt. Der Umfang unterscheidet sich vom übergeordneten Bereich. Im Falle von ng-show werden jedoch nur die Elemente basierend auf dem zugewiesenen Wert angezeigt und ausgeblendet. Aber es bleibt immer im DOM. Nur die Sichtbarkeit ändert sich gemäß dem zugewiesenen Wert.

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

Ich hoffe, dieses Beispiel hilft Ihnen beim Verständnis der Bereiche. Versuchen Sie, ng-show und ng-if falsche Werte zu geben, und überprüfen Sie das DOM in der Konsole. Geben Sie die Werte in die Eingabefelder ein und beobachten Sie den Unterschied.

<!DOCTYPE html>

Hallo 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}}


quelle
2

Tatsache, dass diese ng-ifRichtlinie im Gegensatz zu ng-showihrem eigenen Geltungsbereich einen interessanten praktischen Unterschied schafft:

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>

In der ersten Liste wird on-clickEreignis, showVariable aus dem inneren / eigenen Bereich geändert, es wird jedoch ng-ifeine andere Variable aus dem äußeren Bereich mit demselben Namen überwacht , sodass die Lösung nicht funktioniert. Wenn ng-showwir die einzige showVariable haben, funktioniert sie deshalb. Um den ersten Versuch zu korrigieren, sollten wir über auf den showübergeordneten / äußeren Bereich verweisen $parent.show.

Slava Utesinov
quelle
1
  1. ng-if if false entfernt Elemente aus dem DOM. Dies bedeutet, dass alle Ihre Ereignisse und Anweisungen, die diesen Elementen zugeordnet sind, verloren gehen. Wenn Sie beispielsweise mit der rechten Maustaste auf eines der untergeordneten Elemente klicken und ng-if als false auswertet, wird dieses Element aus dem DOM entfernt und erneut erstellt, wenn es wahr ist.

  2. ng-show / ng-hide entfernt die Elemente nicht aus dem DOM. Es verwendet CSS-Stile (.ng-hide), um Elemente auszublenden / anzuzeigen. Auf diese Weise gehen Ihre Ereignisse und Anweisungen, die an untergeordnete Elemente angehängt wurden, nicht verloren.

  3. ng-if erstellt einen untergeordneten Bereich, ng-show / ng-hide nicht.

Amay Kulkarni
quelle
1

ng-show und ng-hide arbeiten in umgekehrter Weise. Der Unterschied zwischen ng-hide oder ng-show mit ng-if besteht jedoch darin, dass bei Verwendung von ng-if das Element im dom erstellt wird, das Element ng-hide / ng-show jedoch vollständig ausgeblendet wird.

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. 
user1001
quelle
0

Zu beachten, eine Sache, die mir jetzt passiert ist: ng-show verbirgt den Inhalt über CSS, ja, aber es führte zu seltsamen Störungen in Divs, die angeblich Schaltflächen sind.

Ich hatte eine Karte mit zwei Knöpfen auf der Unterseite und je nach aktuellem Zustand wird einer gegen einen dritten ausgetauscht, Beispielbearbeitungsknopf mit neuem Eintrag. Wenn Sie ng-show = false verwenden, um die linke (zuerst in der Datei vorhandene) auszublenden, kam es vor, dass die folgende Schaltfläche mit dem rechten Rand außerhalb der Karte endete. ng-if behebt das, indem der Code überhaupt nicht enthalten ist. (Nur hier überprüft, ob es einige versteckte Überraschungen gibt, wenn ng-if anstelle von ng-show verwendet wird.)

Helius
quelle
0

ngIf nimmt eine Manipulation am DOM vor, indem das Element entfernt oder neu erstellt wird.

Während ngShow eine CSS-Regel anwendet, um Dinge zu verbergen / anzuzeigen .

In den meisten Fällen (nicht immer) würde ich dies wie folgt zusammenfassen: Wenn Sie eine einmalige Überprüfung zum Ein- / Ausblenden von Dingen ng-ifbenötigen , verwenden Sie , wenn Sie Dinge basierend auf den Benutzeraktionen auf dem Bildschirm anzeigen / ausblenden müssen (wie aktiviert) ein Kontrollkästchen dann Textfeld anzeigen, deaktiviert, dann Textfeld ausblenden usw.), dann verwendenng-show

neugierigBoy
quelle
-17

Ein interessanter Unterschied zwischen ng-if und ng-show ist:

SICHERHEIT

Im ng-if-Block vorhandene DOM-Elemente werden im Falle ihres Werts als false nicht gerendert

Wo wie im Fall von ng-show, kann der Benutzer das Inspect Element-Fenster öffnen und seinen Wert auf TRUE setzen.

Und mit einem Whoop werden ganze Inhalte angezeigt, die versteckt werden sollten, was eine Sicherheitsverletzung darstellt. :) :)

Ashish_B
quelle
27
Dies ist eine äußerst schwache Form der Sicherheit. Wenn der Inhalt vom Server an den Client übergeben wird, müssen Sie davon ausgehen, dass der Benutzer / Angreifer darauf zugreifen kann, unabhängig davon, ob er im DOM vorhanden ist oder nicht. Die gesamte Autorisierungslogik muss vom Server erzwungen werden.
Tlrobinson
Denken Sie an HTML anstatt an JSP ... jetzt, wenn Sie die Sicherheit für HTML-Komponenten erzwingen möchten ... dh wenn Sie einige Komponenten vor dem Benutzer verbergen möchten ... wie würden Sie das erreichen? Und was ist, falls Ihre Konfiguration in Server-Seite für Backend und Client-Seite für Front-End unterteilt ist.
Ashish_B