Angular の Change Detection がどのように機能するか、@Input
プロパティの変更を検出するために OnChanges フックを使用する方法、およびディレクティブやコンポーネントなどで ngModel valueChanges をサブスクライブする方法について、私はかなりの情報を得ています。
ここで何が起こっているのか誰でも説明できますか:
# カスタム ディレクティブ:
@Input() プロパティ ngModel を持つカスタム ディレクティブ myNumber があるとします。
@Directive({
selector: "[myNumber]"
})
class MyNumberDirective implements OnChanges {
@Input() ngModel: any;
constructor(private model: NgModel) {
this.model.control.valueChanges.subscribe(data => {
console.log('directive model changes detected by model control value change subscription');
});
}
ngOnChanges(changes: SimpleChanges){
if(changes.ngModel){
console.log('directive input ngModel changes detected by OnChanges hook');
}
}
}
- 上記の例では、サブスクリプションを
@Input
プロパティ ngModel とディレクティブのモデル オブジェクトの変更に設定しました。モデル値が変更された場合、変更はコンソールに記録される必要があります。
# コンポーネントのテンプレート:
<input type="number" myNumber [(ngModel)]="number1" />
<input type="number" myNumber [(ngModel)]="number2" />
<input type="number" myNumber [(ngModel)]="number3" (blur)="calculate()" />
3 つの入力要素に myNumber ディレクティブを適用し、各入力要素には ngModel: number1、number2、number3 があります。
最後の入力には、calculate() メソッドを呼び出すぼかしイベントがあります。
# コンポーネントの typescript:
calculate() {
this.number1 = 10; // changing ngModel of first input
console.log('number1 changed in a calculate method');
this.number2 = 20; // changing ngModel of second input
console.log('number2 changed in a calculate method');
this.number3 = 30; // changing ngModel of third input
console.log('number3 changed in a calculate method');
}
- モデルが変更されるたびに、calculate() メソッドでメッセージをログに記録しました。
- ディレクティブは ngModel の変更をリッスンしており、モデル値の変更ごとに 2 つのメッセージもログに記録します。
# 問題:
Angular はcalculate()
メソッドを実行し、3 つのモデルすべてを変更してから、変更を検出し、ディレクティブで cd フックをトリガーします。
// calculate() log messages first:
'number1 changed in a calculate method'
'number2 changed in a calculate method'
'number3 changed in a calculate method'
// then number1 model change messages in a directive:
'directive model changes detected by model control value change subscription'
'directive input ngModel changes detected by OnChanges hook'
// then number2 model change messages in a directive:
'directive model changes detected by model control value change subscription'
'directive input ngModel changes detected by OnChanges hook'
// then number3 model change messages in a directive:
'directive model changes detected by model control value change subscription'
'directive input ngModel changes detected by OnChanges hook'
# 簡単にしたい解決策:
コンポーネントchangeDetection()
では、メソッドでモデルが変更されるたびに呼び出すことができますcalculate()
。これにより、ディレクティブの変更検出フックが自動的にトリガーされます。
constructor(private ref: ChangeDetectorRef) {}
calculate() {
this.number1 = 10; // changing ngModel of first input
console.log('number1 changed in a calculate method');
this.ref.detectChanges(); // triggering detect changes manually
this.number2 = 20; // changing ngModel of second input
console.log('number2 changed in a calculate method');
this.ref.detectChanges(); // triggering detect changes manually
this.number3 = 30; // changing ngModel of third input
console.log('number3 changed in a calculate method');
this.ref.detectChanges(); // triggering detect changes manually
}
- このように angular はモデルを変更し、ディレクティブ内の変更検出フックをすぐに呼び出します。
# 質問:
ref.detectChanges()
これをすぐに達成し、各モデルの変更後に手動で書き込むことなく検出を変更するにはどうすればよいですか?
この例が、同じ問題を抱えているすべての人に役立つことを願っています