AngularJSでは、の$watch
関数を使用してスコープ変数の変更を監視するウォッチャーを指定することができました$scope
。Angularで変数の変化(コンポーネント変数など)を監視することに相当することは何ですか?
AngularJSでは、の$watch
関数を使用してスコープ変数の変更を監視するウォッチャーを指定することができました$scope
。Angularで変数の変化(コンポーネント変数など)を監視することに相当することは何ですか?
回答:
Angular 2では、変更検出は自動的に行われます... $scope.$watch()
そして$scope.$digest()
RIP
残念ながら、開発ガイドの「変更の検出」セクションはまだ書かれていません(「アーキテクチャの概要」ページの下部、「その他のこと」セクションのプレースホルダーがあります)。
変更検出の仕組みについての私の理解は次のとおりです。
setTimeout()
ようなものではなく、コンポーネントの内部で使用できる理由です。猿がパッチされている$timeout
からsetTimeout()
です。ChangeDetectorRef
。)これらの変更検出器は、Angularがコンポーネントを作成するときに作成されます。ダーティチェックのために、すべてのバインディングの状態を追跡します。これらは、ある意味では、$watches()
Angular 1が{{}}
テンプレートバインディング用にセットアップする自動に似ています。onPush
コンポーネントのいずれかで変更検出戦略を使用していない場合)、ツリー内のすべてのコンポーネントが1回検査されます(TTL = 1)...深さ優先で上から。(まあ、開発モードの場合、変更検出は2回(TTL = 2)実行されます。これについて詳しくは、ApplicationRef.tick()を参照してください。)これらの変更検出オブジェクトを使用して、すべてのバインディングでダーティチェックを実行します。
ngOnChanges()
、変更を通知するように実装できます。 ngDoCheck()
(詳細については、このSOの回答を参照してください)これについて)。 詳細については、その他の参考資料:
onPush
ます。host
で、「ホスト・リスナー」のドキュメントDirectiveMetadataのAPIドキュメントを。Angularゾーン内からグローバルイベントをリッスンする方法を説明します(したがって、変更検出は必要に応じてトリガーされます)。 この回答には効果的なプランカーがあります。
この動作は現在、コンポーネントのライフサイクルの一部です。
コンポーネントは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のウォッチとして機能できます。
こちらのデモをご覧ください。
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);
}
}
モデルにゲッター関数とセッター関数を使用する別のアプローチを次に示します。
@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;
}
}
(change)
それらすべてにハンドラを追加したくありません。get|sets
モデルのすべてのプロパティにs を追加したくありません。get|set
for を追加しても役に立ちませんthis.object
。s ngOnChanges()
へ@Input
の変更のみを検出します。聖なるマナ!彼らは私たちに何をしましたか?ある種のディープウォッチを返してください!
双方向バインディングにしたい場合はを使用でき[(yourVar)]
ますがyourVarChange
、変数を変更するたびにイベントを実装して呼び出す必要があります。
ヒーローの変化を追跡するためのこのようなもの
@Output() heroChange = new EventEmitter();
そしてあなたのヒーローが変わったら、電話して this.heroChange.emit(this.hero);
[(hero)]
あなたのための残りを行いますバインディング
ここの例を参照してください:
アプリケーションがときにこれを試してみてください、まだ要求$parse
、$eval
、$watch
角での動作のように
これは質問に直接答えることはしませんが、角度スタックで$ watchを使用することを解決するために、このスタックオーバーフローの質問にさまざまな場面で遭遇しました。私は現在の回答で説明されているものとは別のアプローチを使用することになりました。
私が同様のことを達成するために使用する手法は、Angularサービスで(詳細についてはこちらのトピックを参照)$watch
を使用し、変更を取得(監視)するためにコンポーネントにサブスクライブさせることです。これはangularJsのa に似ていますが、さらに設定と理解が必要です。BehaviorSubject
$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});
}
}