回答:
ほとんどの場合、使用する必要があります{static: false}
。このように設定すると、バインディングの解決に依存するクエリ構造(構造ディレクティブなど*ngIf, etc...
)が確実に検出されます。
いつ使用するかの例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;
}
これstatic: false
は、Angular 9のデフォルトのフォールバック動作になります。詳しくは、こちらとこちらをご覧ください。
{ static: true }
オプションは、その場で埋め込みビューの作成をサポートするために導入されました。ビューを動的に作成していて、にアクセスしたいTemplateRef
場合はngAfterViewInit
、ExpressionHasChangedAfterChecked
エラーが発生するため、アクセスできません。staticフラグをtrueに設定すると、ngOnInitにビューが作成されます。
それにもかかわらず:
他のほとんどの場合、ベストプラクティスはを使用すること
{static: false}
です。
ただし、この{ static: false }
オプションはAngular 9ではデフォルトになることに注意してください。つまり、オプションを使用したくない場合を除き、静的フラグを設定する必要はありませんstatic: true
。
angular cli ng update
コマンドを使用して、現在のコードベースを自動的にアップグレードできます。
移行ガイドとこれに関するさらに詳しい情報については、こことここで確認できます
静的クエリと動的クエリの違いは何ですか?
@ViewChild()および@ContentChild()クエリの静的オプションは、クエリ結果がいつ利用可能になるかを決定します。
静的クエリ(静的:true)では、ビューが作成された後、変更検出が実行される前にクエリが解決されます。ただし、結果は、ngIfブロックやngForブロックの変更など、ビューの変更を反映するように更新されることはありません。
動的クエリ(静的:false)の場合、クエリは、@ ViewChild()および@ContentChild()のngAfterViewInit()またはngAfterContentInit()の後にそれぞれ解決します。結果は、ngIfブロックやngForブロックの変更など、ビューの変更に対して更新されます。
{ static: true }
、内部ngOnInit
でViewChildにアクセスする必要がない場合は、を使用するだけ{ static: false }
です。
経験則として、次のことを行うことができます。
{ static: true }
あなたがアクセスしたいときのニーズが設定されるViewChild
中をngOnInit
。
{ static: false }
でのみアクセスできますngAfterViewInit
。これは*ngIf
、テンプレートの要素に構造ディレクティブ(つまり)がある場合にも適用したいものです。
角度のドキュメントから
static-変更検出の実行前にクエリ結果を解決するかどうか(つまり、静的な結果のみを返す)。このオプションが指定されていない場合、コンパイラーはデフォルトの動作にフォールバックします。これは、クエリ結果を使用してクエリ解決のタイミングを決定することです。クエリ結果がネストされたビュー(* ngIfなど)内にある場合、クエリは変更検出の実行後に解決されます。それ以外の場合は、変更検出が実行される前に解決されます。
static:true
子供が条件に依存しない場合は、使用することをお勧めします。要素の可視性が変化すると、static:false
より良い結果が得られる可能性があります。
PS:その新機能なので、パフォーマンスのためにベンチマークを実行する必要があるかもしれません。
@Massimiliano Sartorettoが述べたように、github commitはより多くの洞察を与えるかもしれません。
Angular 8にアップグレードした後、ngOnInitでViewChildがnullになったため、ここに来ました。
静的クエリはngOnInitの前に入力され、動的クエリ(静的:false)はその後に入力されます。言い換えると、static:falseを設定した後にngOnInitでviewchildがnullになった場合、static:trueに変更するか、コードをngAfterViewInitに移動することを検討する必要があります。
https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336を参照してください
他の答えは正解であり、これが当てはまる理由を説明しています。ngIf内のViewChild参照などの構造ディレクティブに依存するクエリは、このディレクティブの条件が解決された後、つまり変更が検出された後に実行する必要があります。ただし、static:trueを安全に使用できるため、ネストされていない参照のngOnInitの前にクエリを解決できます。この特定のケースがnull例外であることを指摘した場合、私にとっては、この特殊性に遭遇する最初の方法である可能性があります。
子@angular 5+トークンの2つの引数を表示( 'ローカル参照名'、static:false | true)
@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;
真と偽の違いを知るには、これをチェックしてください
static-変更検出の実行前にクエリ結果を解決するかどうか(つまり、静的な結果のみを返す)。このオプションが指定されていない場合、コンパイラーはデフォルトの動作にフォールバックします。これは、クエリ結果を使用してクエリ解決のタイミングを決定することです。クエリ結果がネストされたビュー(* ngIfなど)内にある場合、クエリは変更検出の実行後に解決されます。それ以外の場合は、変更検出が実行される前に解決されます。
ng8では、親コンポーネントの子コンポーネントにアクセスするタイミングを手動で設定できます。staticをtrueに設定すると、親コンポーネントはコンポーネントの定義のみをonInit
フックで取得します。例:
// You got a childComponent which has a ngIf/for tag
ngOnInit(){
console.log(this.childComponent);
}
ngAfterViewInit(){
console.log(this.childComponent);
}
staticがfalseの場合、ngAfterViewInit()でのみ定義を取得し、ngOnInit()では未定義になります。