Come dovrei usare la nuova opzione statica per @ViewChild in Angular 8?


204

Come devo configurare il nuovo figlio della vista Angular 8?

@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;

vs

@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;

Che è migliore? Quando dovrei usare static:truevs static:false?

Risposte:


237

Nella maggior parte dei casi vorrai usare {static: false}. Impostandolo in questo modo, si troveranno corrispondenze di query dipendenti dalla risoluzione vincolante (come le direttive strutturali *ngIf, etc...).

Esempio di quando usare static: false:

@Component({
  template: `
    <div *ngIf="showMe" #viewMe>Am I here?</div>
    <button (click)="showMe = !showMe"></button>
  ` 
})
export class ExampleComponent {
  @ViewChild('viewMe', { static: false })
  viewMe?: ElementRef<HTMLElement>; 

  showMe = false;
}

Il static: falsecomportamento di fallback predefinito sarà in Angolare 9. Ulteriori informazioni qui e qui

L' { static: true }opzione è stata introdotta per supportare la creazione di viste incorporate al volo. Quando crei una vista in modo dinamico e desideri accedervi TemplateRef, non sarai in grado di farlo ngAfterViewInitpoiché provocherà un ExpressionHasChangedAfterCheckederrore. L'impostazione del flag statico su true creerà la vista in ngOnInit.

Tuttavia:

Nella maggior parte degli altri casi, è consigliabile utilizzare la migliore pratica {static: false}.

Tuttavia, tenere presente che l' { static: false }opzione verrà impostata come predefinita in Angolare 9. Ciò significa che l'impostazione del flag statico non è più necessaria, a meno che non si desideri utilizzare l' static: trueopzione.

È possibile utilizzare il ng updatecomando angular cli per aggiornare automaticamente la base di codice corrente.

Per una guida alla migrazione e ulteriori informazioni a riguardo, puoi consultare qui e qui

Qual è la differenza tra query statiche e dinamiche?

L'opzione statica per le query @ViewChild () e @ContentChild () determina quando saranno disponibili i risultati della query.

Con le query statiche (static: true), la query si risolve una volta creata la vista, ma prima che venga eseguito il rilevamento delle modifiche. Il risultato, tuttavia, non verrà mai aggiornato per riflettere le modifiche alla vista, come le modifiche ai blocchi ngIf e ngFor.

Con le query dinamiche (statiche: false), la query si risolve rispettivamente dopo ngAfterViewInit () o ngAfterContentInit () rispettivamente per @ViewChild () e @ContentChild (). Il risultato verrà aggiornato per le modifiche alla vista, come le modifiche ai blocchi ngIf e ngFor.


Aggiorna il link per i documenti angolari (modificato dopo il rilascio) angular.io/api/core/ViewChild#description
Sachin Gupta

2
Non riesco ad accedere all'istanza di childView. Dice indefinito tutto il tempo.
Nesan Mano,

Potete per favore fornire un link su tali informazioni sulla rimozione dell'opzione statica in Angular 9?
Alex Marinov,

@AlexMarinov Ho aggiornato la mia risposta per chiarire cosa accadrà
nell'angolare

1
@ MinhNghĩa se annidate l'intero componente al di fuori del modello del componente, potete usarlo { static: true }, ma se non vi è alcuna necessità diretta di avere accesso a ViewChild all'interno ngOnInit, dovreste semplicemente usare il file { static: false }.
Poul Kruijt,

88

Quindi, come regola generale, puoi scegliere quanto segue:

  • { static: true }deve essere impostato quando si desidera accedere a ViewChildin ngOnInit.

  • { static: false }è possibile accedere solo in ngAfterViewInit. Questo è anche ciò che vuoi fare quando hai una direttiva strutturale (cioè *ngIf) sul tuo elemento nel tuo modello.


2
Nota: in Angular 9, il flag statico viene impostato automaticamente su false, quindi "tutti i flag {static: false} possono essere rimossi in modo sicuro". Documentazione: angular.io/guide/static-query-migration
Stevethemacguy

17

Dai documenti angolari

statico - se risolvere i risultati della query prima dell'esecuzione del rilevamento delle modifiche (ovvero restituire solo risultati statici). Se questa opzione non viene fornita, il compilatore tornerà al suo comportamento predefinito, ovvero utilizzare i risultati della query per determinare i tempi della risoluzione della query. Se i risultati di una query si trovano all'interno di una vista nidificata (ad es. * NgIf), la query verrà risolta dopo l'esecuzione del rilevamento delle modifiche. In caso contrario, verrà risolto prima dell'esecuzione del rilevamento delle modifiche.

Potrebbe essere un'idea migliore da usare static:truese il bambino non dipende da alcuna condizione. Se la visibilità dell'elemento cambia, è static:falsepossibile che si ottengano risultati migliori.

PS: poiché è una nuova funzionalità, potrebbe essere necessario eseguire benchmark per le prestazioni.

modificare

Come menzionato da @Massimiliano Sartoretto, github commit potrebbe fornirti maggiori spunti.


3
Aggiungerei le motivazioni ufficiali alla base di questa funzione github.com/angular/angular/pull/28810
Massimiliano Sartoretto

2

È venuto qui perché un ViewChild era nullo in ngOnInit dopo l'aggiornamento a Angular 8.

Le query statiche vengono riempite prima di ngOnInit, mentre le query dinamiche (statiche: false) vengono riempite dopo. In altre parole, se un viewchild ora è nullo in ngOnInit dopo aver impostato static: false, dovresti prendere in considerazione la modifica in static: true o spostare il codice in ngAfterViewInit.

Vedi https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336

Le altre risposte sono corrette e spiegano perché questo è il caso: le query dipendenti da direttive strutturali, ad esempio un riferimento ViewChild all'interno di un ngIf, dovrebbero essere eseguite dopo che il condizionale di questa direttiva è stato risolto, cioè dopo il rilevamento delle modifiche. Tuttavia, si può tranquillamente usare static: true e quindi risolvere le query prima di ngOnInit per riferimenti non desiderati. Imho che questo caso particolare menziona come un'eccezione nulla potrebbe essere il primo modo in cui incontrerai questa particolarità, come è stato per me.


1

visualizza due argomenti token @angular 5+ ('nome di riferimento locale', statico: falso | vero)

@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;

per sapere la differenza tra vero e falso controlla questo

statico - se risolvere i risultati della query prima dell'esecuzione del rilevamento delle modifiche (ovvero restituire solo risultati statici). Se questa opzione non viene fornita, il compilatore tornerà al suo comportamento predefinito, ovvero utilizzare i risultati della query per determinare i tempi della risoluzione della query. Se i risultati di una query si trovano all'interno di una vista nidificata (ad es. * NgIf), la query verrà risolta dopo l'esecuzione del rilevamento delle modifiche. In caso contrario, verrà risolto prima dell'esecuzione del rilevamento delle modifiche.


0

In ng8, è possibile impostare manualmente quando accedere al componente figlio nel componente padre. Quando si imposta static su true, significa che il componente parent ottiene solo la definizione del componente nel onInithook: Ad esempio:

 // You got a childComponent which has a ngIf/for tag
ngOnInit(){
  console.log(this.childComponent);
}

ngAfterViewInit(){
  console.log(this.childComponent);
}

Se static è falso, otterrai solo la definizione in ngAfterViewInit (), in ngOnInit (), otterrai una definizione.

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.