1. ホーム
  2. アンギュラー

[解決済み】Angular 8の@ViewChildの新しい静的なオプションはどのように使用すればよいですか?

2022-03-30 11:57:18

質問

Angular 8の新しいビューチャイルドはどのように設定すればよいですか?

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

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

どっちがいい?どのような場合に static:truestatic:false ?

解決方法は?

ほとんどの場合 {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 オプションを使用します。

を使用することで、アンギュラークリ ng update コマンドを使用すると、現在のコードベースを自動的にアップグレードすることができます。

移行ガイドとこれに関するさらに詳しい情報については こちら および こちら

#スタティッククエリとダイナミッククエリの違いは何ですか? ViewChild() および @ContentChild() クエリの static オプションは、 クエリの結果がいつ利用可能になるかを決定します。

<ブロッククオート

静的クエリ (static: true) では、ビューが作成されるとクエリが解決されますが、変更検出が実行される前に解決されます。しかし、その結果は、ngIfやngForブロックへの変更など、ビューへの変更を反映するために更新されることはありません。

<ブロッククオート

動的クエリ(static: false)では、@ViewChild() と @ContentChild() それぞれについて ngAfterViewInit() または ngAfterContentInit() の後でクエリが解決されます。結果は、ngIfやngForブロックへの変更など、ビューへの変更に対して更新されます。


を使用した素敵なユースケースです。 static: true を使用している場合です。 fromEvent を使用して、テンプレートで定義された要素にバインドします。次のようなテンプレートを考えてみましょう。

<div [ngStyle]="thumbStyle$ | async" #thumb></div>

そうすると、サブスクリプションやinitフックを使わなくても、この要素のイベントを処理できるようになります(angularイベントバインディングを使いたくない、あるいは使えない場合)。

@Component({})
export class ThumbComponent {
  @ViewChild('thumb', { static: true })
  thumb?: ElementRef<HTMLElement>;

  readonly thumbStyle$ = defer(() => fromEvent(this.thumb, 'pointerdown').pipe(
    switchMap((startEvent) => fromEvent(document, 'pointermove', { passive: true })
    // transform to proper positioning
  ));
}

を使用することが重要です。 defer . これは、observableが購読されたときだけ解決されることを確認します。これは ngAfterViewInit がトリガーされると async パイプがそれを購読します。なぜなら、私たちは static: true を使用すると this.thumb はすでに入力されています。