9

我非常了解 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。

  • 最后一个输入在 blur 事件上调用 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'

# 解决方案我想简化:

在组件中,我们可以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()如何在每次模型更改后立即实现并更改检测而无需手动编写?

我希望这个例子对所有遇到同样问题的人有用

4

1 回答 1

4

更新:

我第一篇文章中的上述示例实际上是有效的 :) 这是我的错误,我将详细解释。

在我的实际实现中,我将数字指令应用于所有数字输入字段。一个指令正在监听模糊模型的变化并应用一些数字舍入。

一切正常 -> 我们插入一个数字,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(指令)没有在正确的时刻检测到变化。

抱歉,伙计们,但我希望这个订阅检测更改的示例对某人有所帮助!

:: 欢呼 ::

约瑟普

于 2018-04-12T21:44:08.270 回答