Quando preferire ng-if rispetto a ng-show / ng-hide?


Risposte:


703

Dipende dal caso d'uso ma per riassumere la differenza:

  1. ng-ifrimuoverà gli elementi dal DOM. Ciò significa che tutti i gestori o qualsiasi altra cosa collegata a tali elementi andranno persi. Ad esempio, se si associa un gestore di clic a uno degli elementi figlio, quando viene ng-ifvalutato su falso, tale elemento verrà rimosso dal DOM e il gestore di clic non funzionerà più, anche in ng-ifseguito restituisce vero e visualizza l'elemento. Sarà necessario ricollegare il gestore.
  2. ng-show/ng-hidenon rimuove gli elementi da DOM. Usa gli stili CSS per nascondere / mostrare elementi (nota: potrebbe essere necessario aggiungere le tue classi). In questo modo i gestori che erano attaccati ai bambini non andranno persi.
  3. ng-ifcrea un ambito figlio mentre ng-show/ng-hidenon lo fa

Gli elementi che non si trovano nel DOM hanno un impatto minore sulle prestazioni e l'app Web potrebbe sembrare più veloce se utilizzata ng-ifrispetto a ng-show/ng-hide. Nella mia esperienza, la differenza è trascurabile. Le animazioni sono possibili quando si utilizzano entrambi ng-show/ng-hidee ng-if, con esempi per entrambi nella documentazione angolare.

In definitiva, la domanda a cui devi rispondere è se puoi rimuovere l'elemento dal DOM o no?


19
Puoi usare le animazioni CSS3 con ng-if. Controlla il paragrafo Animazioni e l'esempio nei documenti . Anche con ng-hide/ng-showi selettori CSS come :first-childo :nth-childnon funzionerà correttamente poiché verranno conteggiati anche gli elementi nascosti.
Łukasz Wojciechowski il

4
Il servizio di animazione in angular.dart è relativamente nuovo. Al momento della stesura di questo non era disponibile.
markovuksanovic,

44
Innanzi tutto, è un problema se si utilizzano direttive (come ng-click) per associare i gestori, come si dovrebbe essere.
Kevin C.

9
Inoltre, ng-ifcrea un nuovo ambito mentre ng-shownon lo fa.
martin

8
Va anche detto che l'aggiunta e la rimozione di elementi dal DOM può comportare un costo elevato se eseguito frequentemente.
Kevin C.,

130

Vedi qui per una CodePen che dimostra la differenza nel modo in cui ng-if / ng-show funziona, per quanto riguarda il DOM.

@markovuksanovic ha risposto bene alla domanda. Ma mi piacerebbe venire la cosa da un altro punto di vista: avevo sempre usare ng-ife ottenere quegli elementi di DOM, a meno che:

  1. per qualche motivo hai bisogno che i dati e le associazioni $watchsui tuoi elementi rimangano attivi mentre sono invisibili. I moduli potrebbero essere un buon caso per questo, se si desidera essere in grado di verificare la validità degli input che non sono attualmente visibili, al fine di determinare se l'intero modulo è valido.
  2. Stai usando una logica stateful davvero elaborata con i gestori di eventi condizionali, come menzionato sopra. Detto questo , se ti ritrovi ad attaccare e staccare manualmente i gestori, in modo tale da perdere uno stato importante quando usi ng-if, chiediti se quello stato sarebbe meglio rappresentato in un modello di dati e i gestori applicati condizionalmente dalle direttive ogni volta che l'elemento è reso. Detto in altro modo, la presenza / assenza di gestori è una forma di dati di stato. Ottieni quei dati dal DOM e in un modello. La presenza / assenza dei gestori dovrebbe essere determinata dai dati e quindi facile da ricreare.

Angular è scritto davvero bene. È veloce, considerando quello che fa. Ma quello che fa è un sacco di magia che rende le cose difficili (come l'associazione di dati a 2 vie) banalmente facili. Rendere facili tutte queste cose comporta un certo sovraccarico di prestazioni. Potresti essere scioccato nel capire quante centinaia o migliaia di volte una funzione setter viene valutata durante il $digestciclo su un pezzo di DOM che nessuno sta nemmeno guardando. E poi ti rendi conto di avere dozzine o centinaia di elementi invisibili che fanno tutti la stessa cosa ...

I desktop possono infatti essere abbastanza potenti da rendere discutibili la maggior parte dei problemi di velocità di esecuzione di JS. Ma se stai sviluppando per dispositivi mobili, utilizzare ng-if ogni volta che umanamente possibile dovrebbe essere un gioco da ragazzi. La velocità di JS conta ancora sui processori mobili. L'uso di ng-if è un modo molto semplice per ottenere un'ottimizzazione potenzialmente significativa a costi molto, molto bassi.


6
Molto bella aggiunta alla risposta sopra. Dato con un buon contesto, che aiuta anche il processo decisionale. Grazie.
Sean,

1
ng-showpuò essere utile quando hai, ad esempio le schede ognuna con molto contenuto che richiede tempo per il rendering. Dopo il primo rendering, lo spostamento tra le schede sarà istantaneo, mentre ng-ifrichiederebbe il rendering, eventi vincolanti ecc. Il rovescio della medaglia, come dici tu, è che crea orologi in esecuzione in background. Angular ha un disperato bisognong-ifshowwatch
più elegante il

53

Dalla mia esperienza:

1) Se la tua pagina ha un interruttore che usa ng-if / ng-show per mostrare / nascondere qualcosa, ng-if provoca più di un ritardo del browser (più lento). Ad esempio: se si utilizza un pulsante per alternare tra due visualizzazioni, ng-show sembra essere più veloce.

2) ng-if creerà / distruggerà l'ambito quando valuta vero / falso. Se hai un controller collegato a ng-if, quel codice controller verrà eseguito ogni volta che ng-if restituisce true. Se si utilizza ng-show, il codice del controller viene eseguito solo una volta. Quindi se hai un pulsante che commuta tra più viste, l'uso di ng-if e ng-show farebbe una grande differenza nel modo in cui scrivi il codice del controller.


5
Questo è un vero vero! ng-if non rende necessariamente più veloce il tuo frontend. Dipende dai tuoi bisogni. In realtà potrebbe fare il contrario se si utilizza in una situazione sbagliata.
Thiago C. S Ventura,

1
Ma secondo me ng-if non esegue il rendering su DOM, quindi è veloce rispetto a ng-show / hide. mi sbaglio per favore fammi correggere a quel punto.
Pardeep Jain,

1
ng-if sarebbe più veloce se viene valutato falso, poiché, come dici tu, non è necessario inserire nulla nel DOM. Ma, se è vero, allora hai un sovraccarico di inserire l'elemento - forse abbastanza complicato - nel DOM.
Mawg dice di ripristinare Monica il

"2) ng-if creerà / distruggerà l'ambito quando valuterà vero / falso. Se hai un controller collegato a ng-if, quel codice controller verrà eseguito ogni volta che"
The Red Pea

35

La risposta non è semplice:

Dipende dalle macchine target (mobile vs desktop), dipende dalla natura dei tuoi dati, dal browser, dal sistema operativo, dall'hardware su cui gira ... dovrai fare un benchmark se vuoi davvero saperlo.

È principalmente un problema di memoria vs calcolo ... poiché con la maggior parte dei problemi di prestazioni la differenza può diventare significativa con gli elementi ripetuti (n) come le liste, specialmente quando nidificati (nxn o peggio) e anche che tipo di calcoli si esegue all'interno di questi elementi :

  • ng-show : se questi elementi opzionali sono spesso presenti (densi), come diciamo il 90% delle volte, potrebbe essere più veloce averli pronti e mostrarli / nasconderli, specialmente se il loro contenuto è economico (solo testo semplice, niente per calcolare o caricare). Ciò consuma memoria poiché riempie il DOM di elementi nascosti, ma mostrare / nascondere qualcosa che già esiste è probabilmente un'operazione a basso costo per il browser.

  • ng-if : se al contrario è probabile che non vengano mostrati elementi (sparsi) costruiscili e distruggili in tempo reale, specialmente se il loro contenuto è costoso da ottenere (calcoli / ordinati / filtrati, immagini, immagini generate). Questo è l'ideale per elementi rari o "su richiesta", consente di risparmiare memoria in termini di non riempimento del DOM ma può costare molto calcolo (creazione / distruzione di elementi) e larghezza di banda (acquisizione di contenuti remoti). Dipende anche da quanto calcoli nella vista (filtro / ordinamento) rispetto a ciò che hai già nel modello (dati preordinati / pre-filtrati).


2
Altre risposte per fatti tecnici. Questo per saggezza. Hai chiaramente creato app angolari non banali, signore! +1
più elegante

Questo problema va oltre l'angolazione, è un problema fondamentale nell'informatica, c'è un punto da cui un metodo è più efficiente dell'altro. Di solito questo può essere trovato attraverso alcuni benchmark. Quindi potresti anche passare da un metodo all'altro a seconda del conteggio degli articoli ... Argomento simile: math.stackexchange.com/questions/1632739/…
Christophe Roussy,

12

Una nota importante:

ngIf (a differenza di ngShow) di solito crea ambiti figlio che possono produrre risultati imprevisti.

Ho avuto un problema relativo a questo e ho trascorso MOLTO tempo per capire cosa stesse succedendo.

(La mia direttiva stava scrivendo i suoi valori del modello nel campo di applicazione sbagliato.)

Quindi, per risparmiare i capelli, usa ngShow a meno che non corri troppo lentamente.

La differenza di prestazione è quasi impercettibile comunque e non sono ancora sicuro di chi sia il favore senza un test ...


8
L'uso $parent.scopevardi associazioni di dati all'interno di un ngIf correggerà cose come problemi relativi agli ambiti figlio quando si utilizza ngIf
meconroy,

2
Questo non è del tutto vero (il commento originale di @ user2173353, cioè). Se segui le buone pratiche, non avrai problemi. Questa è una regola piuttosto semplice: "se non ci sono punti, stai sbagliando". Vedi qui per una demo di come funziona: bit.ly/1SPv4wL . Un altro grande riferimento (vedi errore n. 2): bit.ly/1QfFeWd > (La mia direttiva stava scrivendo i suoi valori del modello nello scopo sbagliato.) Questo è il risultato di non attenersi alla pratica di cui sopra.
piotr.d

1
@ piotr.d Hai ragione, ma non è qualcosa su cui un principiante potrebbe aver bisogno di concentrarsi e c'è un'altra best practice che dice che è meglio lasciare alla fine miglioramenti delle prestazioni (in particolare miglioramenti delle prestazioni che potrebbero non essere miglioramenti nella realtà ). Ho visto persone mettere ngIfovunque credendo che questo migliorerà le prestazioni. Questo semplicemente non è vero e non si può dire quale sia la migliore ngIfo ngShow, senza un test o un'analisi approfondita nel caso particolare. Quindi, raccomando ancora di dimenticarmene ngIf, fino a quando non si vedono cattive prestazioni o si sa cosa sta facendo
user2173353

2
Buon punto. Ma l'utilizzo di controllerAs rende questo un problema. Vedi, ad esempio, l' opinione di John Papa su controllerAs e vm .
jsruok,

4

ng-se su ng-include e su ng-controller avrà un grande impatto su ng-include non caricherà il parziale richiesto e non elaborerà a meno che il flag sia vero su ng-controller non caricherà il controller a meno che flag non sia vero, ma il problema è quando un flag diventa falso in ng-se rimuoverà dal DOM quando flag diventa vero in questo caso ricaricherà il DOM in questo caso ng-show è migliore, per una volta mostra ng-se è meglio


4

Se si utilizza ng-show or ng-hideil contenuto (ad es. Miniature dal server) verrà caricato indipendentemente dal valore dell'espressione ma verrà visualizzato in base al valore dell'espressione.

Se si utilizza ng-ifil contenuto verrà caricato solo se l'espressione di ng-if viene valutata come vera.

L'uso di ng-if è una buona idea in una situazione in cui caricare dati o immagini dal server e mostrarli solo in base all'interazione degli utenti. In questo modo il tuo caricamento della pagina non sarà bloccato da inutili attività impegnative.


Ciò è particolarmente utile poiché la maggior parte dei browser caricherà le immagini anche se il CSS nasconde i loro contenitori DOM. Di solito cercano solo l' srcattributo del imgtag, quando presente viene caricato!
Christophe Roussy,
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.