Angular 5 指令中的实时变化检测
Angular 5 realtime Change Detection in Directive
我非常了解 Angular 的变更检测是如何工作的,以及我们如何使用 OnChanges 挂钩来检测 @Input
属性变更,以及如何订阅 ngModel valueChanges例如指令或组件等..
谁能解释一下这里发生了什么:
#自定义指令:
假设我们有一个自定义指令 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');
}
}
}
- 在上面的示例中,我将订阅设置为
@Input
属性 ngModel 和指令的模型对象更改。当模型值更改时,应在控制台中记录更改。
#组件模板:
<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。
最后一个输入有调用 calculate() 方法的模糊事件。
# 组件的打字稿:
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 的变化,它也会为每个模型值的变化记录两条消息。
#问题:
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
}
- 这样 angular 将更改模型并立即调用指令内的更改检测挂钩。
#问题:
如何在每次模型更改后无需手动编写 ref.detectChanges()
立即实现这一点并更改检测?
希望这个例子对遇到同样问题的各位有用
更新:
我第一个 post 中的上述示例实际上有效:) 这是我的错误,我会详细解释它。
在我的实际实现中,我将数字指令应用于所有数字输入字段。
指令正在侦听模糊模型更改并应用一些数字舍入。
一切正常 -> 我们插入一个数字,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(指令)没有在正确的时刻检测到变化。
抱歉,伙计们,但我希望这个订阅检测变化的例子能对别人有所帮助!!
:: 欢呼::
约瑟普
我非常了解 Angular 的变更检测是如何工作的,以及我们如何使用 OnChanges 挂钩来检测 @Input
属性变更,以及如何订阅 ngModel valueChanges例如指令或组件等..
谁能解释一下这里发生了什么:
#自定义指令:
假设我们有一个自定义指令 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');
}
}
}
- 在上面的示例中,我将订阅设置为
@Input
属性 ngModel 和指令的模型对象更改。当模型值更改时,应在控制台中记录更改。
#组件模板:
<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。
最后一个输入有调用 calculate() 方法的模糊事件。
# 组件的打字稿:
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 的变化,它也会为每个模型值的变化记录两条消息。
#问题:
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
}
- 这样 angular 将更改模型并立即调用指令内的更改检测挂钩。
#问题:
如何在每次模型更改后无需手动编写 ref.detectChanges()
立即实现这一点并更改检测?
希望这个例子对遇到同样问题的各位有用
更新:
我第一个 post 中的上述示例实际上有效:) 这是我的错误,我会详细解释它。
在我的实际实现中,我将数字指令应用于所有数字输入字段。 指令正在侦听模糊模型更改并应用一些数字舍入。
一切正常 -> 我们插入一个数字,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(指令)没有在正确的时刻检测到变化。
抱歉,伙计们,但我希望这个订阅检测变化的例子能对别人有所帮助!!
:: 欢呼::
约瑟普