224

$watchAngularJS では、 の関数を使用してスコープ変数の変更を監視するウォッチャーを指定できました$scope。Angular で変数の変更 (たとえば、コンポーネント変数) を監視することと同等のものは何ですか?

4

8 に答える 8

280

Angular 2 では、変更検出は自動です...$scope.$watch()そして$scope.$digest()RIP

残念ながら、開発ガイドの変更検出セクションはまだ作成されていません (アーキテクチャの概要ページの下部にある「その他のもの」セクションにプレースホルダーがあります)。

変更検出がどのように機能するかについての私の理解は次のとおりです。

  • Zone.js は「モンキー パッチを世界に」 -- ブラウザー内のすべての非同期 API をインターセプトします (Angular の実行時)。これが、...setTimeout()のようなものではなく、コンポーネント内で使用できる理由です。$timeoutsetTimeout()
  • Angular は、「変更検出器」のツリーを構築および維持します。コンポーネント/ディレクティブごとに、そのような変更検出器 (クラス) が 1 つあります。( を注入することで、このオブジェクトにアクセスできますChangeDetectorRef。) これらの変更検出器は、Angular がコンポーネントを作成するときに作成されます。ダーティチェックのために、すべてのバインディングの状態を追跡します。これらはある意味で、 Angular 1 がテンプレート バインディング$watches()用にセットアップする自動化に似ています。Angular 1 とは異なり、変更検出グラフは有向ツリーであり、サイクルを持つことはできません (これにより、以下で説明するように、Angular 2 のパフォーマンスが大幅に向上します)。{{}}
  • イベントが発生すると (Angular ゾーン内で)、作成したコード (イベント ハンドラー コールバック) が実行されます。共有アプリケーションのモデル/状態および/またはコンポーネントのビュー状態など、必要なデータを更新できます。
  • その後、Zone.js が追加したフックにより、Angular の変更検出アルゴリズムが実行されます。デフォルトでは (つまり、onPushどのコンポーネントでも変更検出戦略を使用していない場合)、ツリー内のすべてのコンポーネントが 1 回 (TTL=1) ... 上から深さ優先順に検査されます。(開発モードの場合、変更検出は 2 回 (TTL=2) 実行されます。詳細については、 ApplicationRef.tick()を参照してください。) これらの変更検出オブジェクトを使用して、すべてのバインディングに対してダーティ チェックを実行します。
    • ライフサイクル フックは、変更検出の一部として呼び出されます。
      監視したいコンポーネントデータがプリミティブな入力プロパティ(文字列、ブール値、数値)の場合ngOnChanges()、変更を通知するように実装できます。
      入力プロパティが参照型 (オブジェクト、配列など) であるが、参照が変更されていない場合 (たとえば、既存の配列に項目を追加した場合)、実装する必要がありますngDoCheck()(詳細については、この SO の回答を参照してください)。これについて)。
      コンポーネントのプロパティおよび/または子孫コンポーネントのプロパティのみを変更する必要があります (単一ツリー ウォークの実装、つまり単方向データ フローのため)。これに違反するプランカーがあります。ステートフル パイプもここでつまずく可能性があります
  • バインディングの変更が見つかった場合は、コンポーネントが更新され、次に DOM が更新されます。変更の検出が終了しました。
  • ブラウザーは DOM の変更を認識し、画面を更新します。

詳細については、その他の参考文献をご覧ください。

于 2016-01-02T19:58:30.027 に答える
71

自動双方向バインディングに加えて、値が変更されたときに関数を呼び出す場合は、双方向バインディングのショートカット構文をより詳細なバージョンに分割できます。

<input [(ngModel)]="yourVar"></input>

の省略形です

<input [ngModel]="yourVar" (ngModelChange)="yourVar=$event"></input>

(例: http://victorsavkin.com/post/119943127151/angular-2-template-syntaxを参照)

次のようなことができます。

<input [(ngModel)]="yourVar" (ngModelChange)="changedExtraHandler($event)"></input>

于 2016-01-19T10:38:57.843 に答える
17

getter functionorを使用get accessorして、Angular 2 のウォッチとして機能させることができます。

ここでデモを参照してください。

import {Component} from 'angular2/core';

@Component({
  // Declare the tag name in index.html to where the component attaches
  selector: 'hello-world',

  // Location of the template for this component
  template: `
  <button (click)="OnPushArray1()">Push 1</button>
  <div>
    I'm array 1 {{ array1 | json }}
  </div>
  <button (click)="OnPushArray2()">Push 2</button>
  <div>
    I'm array 2 {{ array2 | json }}
  </div>
  I'm concatenated {{ concatenatedArray | json }}
  <div>
    I'm length of two arrays {{ arrayLength | json }}
  </div>`
})
export class HelloWorld {
    array1: any[] = [];
    array2: any[] = [];

    get concatenatedArray(): any[] {
      return this.array1.concat(this.array2);
    }

    get arrayLength(): number {
      return this.concatenatedArray.length;
    }

    OnPushArray1() {
        this.array1.push(this.array1.length);
    }

    OnPushArray2() {
        this.array2.push(this.array2.length);
    }
}
于 2016-07-29T11:17:56.120 に答える
8

双方向バインディングにしたい場合は、を使用できますが、変数を変更するたびにイベント[(yourVar)]を実装yourVarChangeして呼び出す必要があります。

ヒーローの変更を追跡するためのこのようなもの

@Output() heroChange = new EventEmitter();

そして、あなたのヒーローが変わったら、電話してくださいthis.heroChange.emit(this.hero);

バインディングは[(hero)]あなたのために残りを行います

ここで例を参照してください:

http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview

于 2016-03-02T16:31:48.070 に答える