我非常了解Angular的变更检测是如何工作的,以及我们如何使用OnChanges钩子来检测@Input属性变化,以及订阅ngModel valueChanges,例如指令或组件等。
任何人都可以在这里发生什么:
#Custom Directive:
假设我们有一个自定义指令myNumber,它具有@Input()属性ngModel:
@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');
}
}
}
#Component的模板:
<input type="number" myNumber [(ngModel)]="number1" />
<input type="number" myNumber [(ngModel)]="number2" />
<input type="number" myNumber [(ngModel)]="number3" (blur)="calculate()" />
我们在三个输入元素上应用了myNumber指令,每个输入元素都有ngModel:number1,number2,number3。
上次输入有on blur事件以调用calculate()方法。
#Component的打字稿:
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');
}
#问题:
Angular将执行calculate()方法,更改所有三个模型,然后在指令中检测更改并触发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'
#解决方案我想简化:
在组件中,我们可以在calculate()方法中的每个模型更改后调用changeDetection()。这将自动触发指令的变化检测钩子。
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
}
#问题:
如何在每次模型更改后手动写入ref.detectChanges()时立即更改检测?
非常感谢先进!!
我希望这个例子对所有遇到同样问题的人都有用;)
::干杯::
约瑟普布罗兹
答案 0 :(得分:2)
<强>更新强>
我的第一篇文章中的上述示例实际上正在工作:)这是我的错误,我将详细解释。
在我的实际实现中,我将number指令应用于所有数字输入字段。 指令正在监听模糊模型的变化并应用一些数字舍入。
一切正常 - &gt;我们插入一个数字,onBlur数字将被舍入,应用管道等。
问题在于我有额外的计算方法来重新计算另一个字段:
例如:
calculate() {
this.number1 = 10; // changing ngModel of number1
// after model change number1 will be rounded (handled) in a directive
const number2 = 20; // this is not a model so it's not handled by directive
// I used non-model variable in my calculation that is not handled by directive
this.number3 = this.number1 * number2; // changing ngModel of number3
}
在计算中使用非模型变量 - 该值未舍入,因此我在方法与指令计算舍入中出现不匹配,导致数字略有不同。
这就是为什么我认为Angular(指令)没有在正确的时刻发现变化。
对不起家伙,但我希望这个订阅检测更改的例子能帮助别人!!
::干杯::
约瑟普布罗兹