AngularJSでは、$watch
の$scope
関数を使用してスコープ変数の変更を監視するウォッチャーを指定できました。 Angularで変数の変更(コンポーネント変数など)を監視するのと同じことは何ですか?
Angular 2では、変更の検出は自動的に行われます... $scope.$watch()
および$scope.$digest()
R.I.P.
残念ながら、開発ガイドの変更検出セクションはまだ書かれていません( Architecture Overview ページのセクション "The Other Stuff"の下部にプレースホルダーがあります)。
変更検出の仕組みについての私の理解は次のとおりです。
setTimeout()
はモンキーパッチが適用されているため、$timeout
...のようなものではなく、コンポーネント内でsetTimeout()
を使用できる理由です。ChangeDetectorRef
を挿入します。)これらの変更検出器は、Angularがコンポーネントを作成するときに作成されます。ダーティチェックのために、すべてのバインディングの状態を追跡します。これらは、ある意味で、Angular 1が{{}}
テンプレートバインディングに設定する自動$watches()
に似ています。onPush
変更検出戦略を使用していない場合)、ツリー内のすべてのコンポーネントが1回(TTL = 1)...上から深さ優先順に検査されます。 (まあ、開発モードの場合、変更検出は2回実行されます(TTL = 2)。詳細については ApplicationRef.tick() を参照してください。)すべてのバインディングに対してダーティチェックを実行します。これらの変更検出器オブジェクトを使用します。ngOnChanges()
を実装できます。ngDoCheck()
( this SO answer を参照してください)。その他の参考資料:
onPush
について少し話しています。この動作は現在、コンポーネントライフサイクルの一部です。
コンポーネントは OnChanges インターフェースにngOnChangesメソッドを実装して、入力の変更にアクセスすることができます。
例:
import {Component, Input, OnChanges} from 'angular2/core';
@Component({
selector: 'hero-comp',
templateUrl: 'app/components/hero-comp/hero-comp.html',
styleUrls: ['app/components/hero-comp/hero-comp.css'],
providers: [],
directives: [],
pipes: [],
inputs:['hero', 'real']
})
export class HeroComp implements OnChanges{
@Input() hero:Hero;
@Input() real:string;
constructor() {
}
ngOnChanges(changes) {
console.log(changes);
}
}
自動双方向バインディングに加えて、値が変更されたときに関数を呼び出す場合は、双方向バインディングのショートカット構文をより冗長なバージョンに変更できます。
<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>
getter function
またはget accessor
を使用して、角度2を監視することができます。
Demo here を参照してください。
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);
}
}
モデルにゲッター関数とセッター関数を使用するもう1つの方法があります。
@Component({
selector: 'input-language',
template: `
…
<input
type="text"
placeholder="Language"
[(ngModel)]="query"
/>
`,
})
export class InputLanguageComponent {
set query(value) {
this._query = value;
console.log('query set to :', value)
}
get query() {
return this._query;
}
}
双方向バインディングにしたい場合は、[(yourVar)]
を使用できますが、変数が変わるたびにyourVarChange
イベントを実装して呼び出す必要があります。
このような何かが主人公の変化を追跡するために
@Output() heroChange = new EventEmitter();
そして、あなたのヒーローが変わったら、this.heroChange.emit(this.hero);
を呼び出してください。
[(hero)]
バインディングがあなたのために残りをします
ここの例を見なさい:
あなたのアプリケーションの still がAngularで$parse
、$eval
、$watch
のような振る舞いを要求するときに試してみてください。
これは直接質問に答えるものではありませんが、私はAngularJで$ watchを使用することになるものを解決するために、このStack Overflowの質問にさまざまな機会を与えました。私は現在の答えで説明されているのとは別のアプローチを使用することになりました、そして誰かがそれを有用であると思う場合に備えてそれを共有したいです。
私が$watch
に似たようなものを実現するのに使うテクニックは、AngularサービスでBehaviorSubject
( こちらのトピックの詳細 )を使い、私のコンポーネントにそれを購読させることです。変更を監視します。これはangularJの$watch
に似ていますが、もう少しセットアップと理解が必要です。
私のコンポーネントでは:
export class HelloComponent {
name: string;
// inject our service, which holds the object we want to watch.
constructor(private helloService: HelloService){
// Here I am "watching" for changes by subscribing
this.helloService.getGreeting().subscribe( greeting => {
this.name = greeting.value;
});
}
}
私のサービスでは
export class HelloService {
private helloSubject = new BehaviorSubject<{value: string}>({value: 'hello'});
constructor(){}
// similar to using $watch, in order to get updates of our object
getGreeting(): Observable<{value:string}> {
return this.helloSubject;
}
// Each time this method is called, each subscriber will receive the updated greeting.
setGreeting(greeting: string) {
this.helloSubject.next({value: greeting});
}
}
これが Stackblitz のデモです。