1. ホーム
  2. angular

[解決済み] Angularで@Input()の値が変更されたときに検出する方法は?

2022-03-14 23:59:31

質問

親コンポーネント( カテゴリコンポーネント )、子コンポーネント( videoListComponent ) とApiServiceがあります。

例えば、各コンポーネントはjson APIにアクセスし、observablesを介して関連データを取得することができます。

現在、動画リスト コンポーネントはすべての動画を取得するだけですが、これを特定のカテゴリに属する動画だけにフィルタリングしたいと考え、カテゴリ ID を @Input() .

CategoryComponent.html

<video-list *ngIf="category" [categoryId]="category.id"></video-list>

これは動作し、親 CategoryComponent のカテゴリが変更されると、categoryId 値が @Input() しかし、VideoListComponent でこれを検出し、APIService を介して (新しい categoryId で) 動画の配列を再要求する必要があります。

AngularJSの場合、私なら $watch を変数に追加します。これを処理する最良の方法は何でしょうか?

どのように解決するのですか?

実は、angular2+の子コンポーネントで入力が変化したことを検知して対処するには、2つの方法があります。

  1. を使用することができます。 ngOnChanges() ライフサイクルメソッド 古い回答にもあるように
    @Input() categoryId: string;
        
    ngOnChanges(changes: SimpleChanges) {
        
        this.doSomething(changes.categoryId.currentValue);
        // You can also use categoryId.previousValue and 
        // categoryId.firstChange for comparing old and new values
        
    }
    

ドキュメントのリンクです。 ngOnChanges, SimpleChanges, シンプルチェンジ
デモの例 見る このプランカー

  1. また 入力プロパティセッター を以下のように設定します。
    private _categoryId: string;
    
    @Input() set categoryId(value: string) {
    
       this._categoryId = value;
       this.doSomething(this._categoryId);
    
    }
    
    get categoryId(): string {
    
        return this._categoryId;
    
    }

ドキュメントのリンクです。見る こちら .

デモの例。見てください このプランカー .

どのようなアプローチをとるべきでしょうか?

コンポーネントに複数の入力がある場合、ngOnChanges() を使用すると、ngOnChanges() 内ですべての入力の変更を一度に取得します。このアプローチを使用すると、変更された入力の現在と以前の値を比較し、それに応じてアクションを実行することもできます。

しかし、特定のひとつの入力だけが変化したときに何かしたい (そして他の入力は気にしない) 場合は、入力プロパティ・セッターを使うほうがシンプルかもしれません。しかし、この方法は、変更された入力の前と現在の値を比較する内蔵の方法を提供しません(ngOnChangesライフサイクルメソッドを使用して簡単に行うことができます)。

2017-07-25を編集しました。angularの変更検出は、いくつかの状況下でまだ発火しないかもしれない

通常、セッターと ngOnChanges の両方に対する変更検出は、親コンポーネントが子コンポーネントに渡すデータを変更するたびに発生します。 ただし、そのデータがJSプリミティブデータタイプ(文字列、数値、ブーリアン)である場合に限ります。 . しかし、次のようなシナリオでは、これは発生しないので、動作させるためには、余分なアクションを行う必要があります。

  1. 親から子へデータを渡すために(JSプリミティブデータタイプの代わりに)ネストされたオブジェクトや配列を使っている場合、(セッターやngchangesを使った)変更検出が行われないことがあります。解決策については、以下をご覧ください。 こちら .

  2. もし、angularのコンテキストの外側(つまり、外部)でデータを変異させている場合、angularはその変更を知ることができません。外部からの変更をangularに認識させ、それによって変更検出をトリガーするために、あなたのコンポーネントでChangeDetectorRefまたはNgZoneを使用する必要があるかもしれません。以下を参照してください。 これ .