Sto cercando di capire la differenza tra ng-if
e ng-show
/ ng-hide
, ma mi sembrano uguali.
C'è una differenza che dovrei tenere a mente scegliendo di usare l'uno o l'altro?
Sto cercando di capire la differenza tra ng-if
e ng-show
/ ng-hide
, ma mi sembrano uguali.
C'è una differenza che dovrei tenere a mente scegliendo di usare l'uno o l'altro?
Risposte:
La ngIf
direttiva rimuove o ricrea una parte dell'albero DOM in base a un'espressione. Se l'espressione assegnata a ngIf
restituisce 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 ngIf
suo ambito viene distrutto e un nuovo ambito viene creato quando l'elemento viene ripristinato. L'ambito creato all'interno ngIf
eredita dal suo ambito padre usando l'ereditarietà prototipale.
Se ngModel
viene utilizzato all'interno ngIf
per 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, $parent
variabile 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>
La ngShow
direttiva mostra o nasconde l'elemento HTML specificato in base all'espressione fornita ngShow
all'attributo. L'elemento viene mostrato o nascosto rimuovendo o aggiungendo la ng-hide
classe CSS sull'elemento. La .ng-hide
classe CSS è predefinita in AngularJS e imposta lo stile di visualizzazione su nessuno (usando un !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>
Quando l' ngShow
espressione restituisce una valutazione, false
la ng-hide
classe CSS viene aggiunta class
all'attributo sull'elemento facendolo diventare nascosto. Quando true
, la ng-hide
classe CSS viene rimossa dall'elemento facendo in modo che l'elemento non appaia nascosto.
data.input
funziona ... ma data
da solo nel modello non funziona. @CodeHater
ngIf
crea un nuovo ambito, quindi guardando l'esempio sopra il nidificato ngModel
creerebbe un nuovo data
modello 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. :)
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.
La ng-if
direttiva rimuove il contenuto dalla pagina e ng-show/ng-hide
utilizza la display
proprietà CSS per nascondere il contenuto.
Ciò è utile nel caso in cui si desideri utilizzare :first-child
e :last-child
pseudo selettori per lo stile.
:first-child
e :last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
@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.
Una cosa importante da notare su ng-if e ng-show è che quando si usano i controlli dei form è meglio usarli ng-if
perché 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 è required
ma 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!
@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>
<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}}
Infatti, tale ng-if
direttiva, a differenza del ng-show
suo 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-click
evento, show
variabile, dall'interno / proprio ambito, viene modificato, ma ng-if
sta osservando un'altra variabile dall'ambito esterno con lo stesso nome, quindi la soluzione non funziona. Nel caso di ng-show
abbiamo l'unica show
variabile, ecco perché funziona. Per risolvere il primo tentativo, dovremmo fare riferimento a show
da ambito genitore / esterno tramite $parent.show
.
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.
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.
ng-if crea un ambito figlio mentre ng-show / ng-hide no.
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.
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)
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
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. :)
ng-if
il modello, aggiunto dang-model
, non esiste più.