Qual è la differenza tra ng-if e ng-show / ng-hide


Risposte:


521

ngIf

La ngIfdirettiva rimuove o ricrea una parte dell'albero DOM in base a un'espressione. Se l'espressione assegnata a ngIfrestituisce un valore falso, l'elemento viene rimosso dal DOM, altrimenti un clone dell'elemento viene reinserito nel 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>

Quando un elemento viene rimosso usando il ngIfsuo ambito viene distrutto e un nuovo ambito viene creato quando l'elemento viene ripristinato. L'ambito creato all'interno ngIferedita dal suo ambito padre usando l'ereditarietà prototipale.

Se ngModelviene utilizzato all'interno ngIfper associare una primitiva JavaScript definita nell'ambito genitore, eventuali modifiche apportate alla variabile all'interno dell'ambito figlio non influiranno sul valore nell'ambito genitore, ad es.

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

Per aggirare questa situazione e aggiornare il modello nell'ambito secondario dall'ambito secondario, utilizzare un oggetto:

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

Oppure, $parentvariabile per fare riferimento all'oggetto ambito genitore:

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

ngShow

La ngShowdirettiva mostra o nasconde l'elemento HTML specificato in base all'espressione fornita ngShowall'attributo. L'elemento viene mostrato o nascosto rimuovendo o aggiungendo la ng-hideclasse CSS sull'elemento. La .ng-hideclasse CSS è predefinita in AngularJS e imposta lo stile di visualizzazione su nessuno (usando un !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>

Quando l' ngShowespressione restituisce una valutazione, falsela ng-hideclasse CSS viene aggiunta classall'attributo sull'elemento facendolo diventare nascosto. Quando true, la ng-hideclasse CSS viene rimossa dall'elemento facendo in modo che l'elemento non appaia nascosto.


31
Suggerimento: rimuovendo l'elemento HTML stesso con ng-ifil modello, aggiunto da ng-model, non esiste più.
mrzmyr,

3
@CodeHater Ho sfruttato con successo ng-if su ng-show / ng-hide su una pagina che altrimenti avrebbe avuto una grande dom. Sembrava per rendere la pagina si sentono più veloce, ma non è affatto di analisi scientifica.
Ed Spencer,

La parte che sto riscontrando problemi con la piena comprensione è come / perché quando hai un oggetto nel modello data.inputfunziona ... ma datada solo nel modello non funziona. @CodeHater
Mark Pieszak - Trilon.io,

7
@mcpDESIGNS ngIfcrea un nuovo ambito, quindi guardando l'esempio sopra il nidificato ngModelcreerebbe un nuovo datamodello anche se esiste un modello con lo stesso nome nell'ambito genitore. Ma quando usi una notazione a punti, fai in modo che JS cerchi la catena di prototipi dell'oscilloscopio. Quindi, se non trova il valore nell'ambito corrente, proverà a cercarlo nell'ambito padre e così via. Poche altre direttive che creano un ambito diverso sono ngInclude, ngRepeat. Spero sia chiaro ora. :)
AlwaysALearner,

3
Quale è meglio per le prestazioni? Penso che ng-show e ng-hide non sia vero?
tom10271

97

Forse un punto interessante da sottolineare è la differenza tra le priorità tra i due.

Per quanto ne so, la direttiva ng-if ha una delle priorità più alte (se non la più alta) di tutte le direttive angolari. Ciò significa che verrà eseguito PRIMA prima di tutte le altre direttive con priorità inferiore. Il fatto che sia eseguito PRIMO, significa che l'elemento viene rimosso in modo efficace prima che vengano elaborate eventuali direttive interne . O almeno: ecco cosa ne faccio.

Ho osservato e usato questo nell'interfaccia utente che sto costruendo per il mio attuale cliente. L'intera interfaccia utente è piuttosto pesante e aveva ng-show e ng-hide dappertutto. Non per entrare troppo nei dettagli, ma ho creato un componente generico, che potrebbe essere gestito usando la configurazione JSON, quindi ho dovuto fare qualche passaggio all'interno del modello. C'è un presente di ng-repeat e all'interno di ng-repeat viene mostrata una tabella che presenta molti ng-show, ng-hides e persino ng-switch presenti. Volevano mostrare almeno 50 ripetizioni nell'elenco, il che avrebbe comportato la risoluzione di circa 1500-2000 direttive. Ho controllato il codice e il backend Java + JS personalizzato sulla parte frontale impiegava circa 150 ms per elaborare i dati, e poi Angular ci masticava circa 2-3 secondi prima di visualizzarlo. Il cliente non si è lamentato, ma sono rimasto sconvolto :-)

Nella mia ricerca, mi sono imbattuto nella direttiva ng-if. Ora, forse è meglio sottolineare che al momento di concepire questa interfaccia utente, non c'era ng-se disponibile. Poiché ng-show e ng-hide avevano funzioni al loro interno, che restituivano valori booleani, potevo facilmente sostituirli tutti con ng-if. In tal modo, tutte le direttive interne sembravano non essere più valutate. Ciò significava che sono tornato a circa un terzo di tutte le direttive in fase di valutazione e, quindi, l'interfaccia utente ha accelerato fino a circa 500 ms - 1 secondo di tempo di caricamento. (Non ho modo di determinare i secondi esatti)

Nota: il fatto che le direttive non siano valutate, è un'ipotesi istruita su ciò che sta accadendo sotto.

Quindi, secondo me: se hai bisogno che l'elemento sia presente sulla pagina (es .: per controllare l'elemento, o qualunque altra cosa), ma semplicemente per essere nascosto, usa ng-show / ng-hide. In tutti gli altri casi, utilizzare ng-if.


1
Sì, suppongo che questo sia l'obiettivo di ng-if: ridurre i tempi di elaborazione. Questa direttiva esiste sicuramente non solo per alcuni pseudoselettori CSS. Buon post! +1
Bartłomiej Zalewski


16

@EdSpencer è corretto. Se hai molti elementi e usi ng-if solo per creare un'istanza di quelli rilevanti, stai risparmiando risorse. Anche @CodeHater è in qualche modo corretto, se hai intenzione di rimuovere e mostrare un elemento molto spesso, nasconderlo invece di rimuoverlo potrebbe migliorare le prestazioni.

Il caso d'uso principale che trovo per ng-if è che mi consente di validare in modo pulito ed eliminare un elemento se il contenuto è illegale. Ad esempio, potrei fare riferimento a una variabile di nome immagine null e ciò genererà un errore, ma se io ng-if e controllo se è null, va tutto bene. Se avessi fatto un ng-show, l'errore sarebbe ancora attivo.


7

Una cosa importante da notare su ng-if e ng-show è che quando si usano i controlli dei form è meglio usarli ng-ifperché rimuove completamente l'elemento dal dom.

Questa differenza è importante perché se crei un campo di input con required="true"e poi imposti ng-show="false"a nasconderlo, Chrome genererà il seguente errore quando l'utente tenta di inviare il modulo:

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

Il motivo è il campo di input presente ed è requiredma poiché è nascosto Chrome non può concentrarsi su di esso. Questo può letteralmente violare il codice poiché questo errore interrompe l'esecuzione dello script. Quindi sii attento!


Questo è il fatto reale, se si utilizzano i controlli del modulo per la convalida, si soffrirà molto se si utilizza ng-show / ng-hide. E se hai più sezioni nascoste / mostra in base all'espressione. Quindi se usi ng-show / hide gli elementi saranno ancora lì e la validazione fallirà, nonostante non siano sullo schermo. così se salvarti :)
NeverGiveUp161

5

@Gajus Kuizinas e @CodeHater sono corretti. Qui sto solo facendo un esempio. Mentre stiamo lavorando con ng-if, se il valore assegnato è falso, tutti gli elementi html verranno rimossi da DOM. e se il valore assegnato è true, gli elementi html saranno visibili sul DOM. E l'ambito sarà diverso rispetto all'ambito padre. Ma in caso di ng-show, mostrerà e nasconderà gli elementi in base al valore assegnato. Ma rimane sempre nel DOM. Solo la visibilità cambia secondo il valore assegnato.

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

Spero che questo esempio ti aiuti a comprendere gli ambiti. Prova a fornire valori falsi a ng-show e ng-if e controlla il DOM nella console. Prova a inserire i valori nelle caselle di input e osserva la differenza.

<!DOCTYPE html>

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


2

Infatti, tale ng-ifdirettiva, a differenza del ng-showsuo ambito di applicazione, crea interessanti differenze pratiche:

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>

Al primo elenco, on-clickevento, showvariabile, dall'interno / proprio ambito, viene modificato, ma ng-ifsta osservando un'altra variabile dall'ambito esterno con lo stesso nome, quindi la soluzione non funziona. Nel caso di ng-showabbiamo l'unica showvariabile, ecco perché funziona. Per risolvere il primo tentativo, dovremmo fare riferimento a showda ambito genitore / esterno tramite $parent.show.


1
  1. ng-if if false rimuoverà gli elementi dal DOM. Ciò significa che tutti i tuoi eventi, le direttive associate a tali elementi andranno persi. Ad esempio, ng-clic su uno degli elementi figlio, quando ng-if restituisce falso, quell'elemento verrà rimosso dal DOM e di nuovo quando è vero viene ricreato.

  2. ng-show / ng-hide non rimuove gli elementi da DOM. Usa gli stili CSS (.ng-hide) per nascondere / mostrare elementi. In questo modo i tuoi eventi, le direttive che sono state attaccate ai bambini non andranno persi.

  3. ng-if crea un ambito figlio mentre ng-show / ng-hide no.


1

ng-show e ng-hide funzionano in modo opposto. Ma la differenza tra ng-hide o ng-show con ng-if è, se usiamo ng-if allora l'elemento verrà creato nel dom ma con l'elemento ng-hide / ng-show verrà completamente nascosto.

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. 

0

Da notare, una cosa che mi è successa ora: ng-show nasconde il contenuto tramite CSS, sì, ma ha provocato strani anomalie nei div che dovrebbero essere pulsanti.

Avevo una carta con due pulsanti nella parte inferiore e, a seconda dello stato reale, uno viene scambiato con un terzo, esempio pulsante di modifica con una nuova voce. Usando ng-show = false per nascondere quello di sinistra (presente per primo nel file) è accaduto che il seguente pulsante finisse con il bordo destro esterno alla carta. ng-if risolve questo problema non includendo affatto il codice. (Ho appena controllato qui se ci sono alcune sorprese nascoste usando ng-if invece di ng-show)


0

ngIf modifica il DOM rimuovendo o ricreando l'elemento.

Considerando che ngShow applica le regole CSS per nascondere / mostrare le cose.

Per la maggior parte dei casi (non sempre) , vorrei riassumere questo come, se hai bisogno di un controllo una volta per mostrare / nascondere le cose, usa ng-if, se hai bisogno di mostrare / nascondere le cose in base alle azioni dell'utente sullo schermo (come spuntate una casella di controllo quindi mostra casella di testo, deselezionata quindi nascondi casella di testo ecc.), quindi utilizzang-show


-17

Una differenza interessante in ng-if e ng-show è:

SICUREZZA

Gli elementi DOM presenti nel blocco ng-if non verranno resi in caso il suo valore sia falso

dove come nel caso di ng-show, l'utente può aprire la finestra Inspect Element e impostarne il valore su TRUE.

E con un urlo, vengono visualizzati interi contenuti che dovevano essere nascosti, il che rappresenta una violazione della sicurezza. :)


27
Questa è una forma di sicurezza estremamente debole. Se il contenuto viene fornito al client dal server, è necessario presupporre che l'utente / utente malintenzionato possa accedervi, indipendentemente dal fatto che sia presente o meno nel DOM. Tutta la logica di autorizzazione deve essere applicata dal server.
tlrobinson,

pensa a html piuttosto che a jsp ... ora se vuoi imporre la sicurezza sui componenti html .. se vuoi nascondere alcuni componenti all'utente ... come lo faresti. E nel caso in cui la configurazione sia divisa in lato server per backend e lato client per front-end ..
Ashish_B
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.