指令

时间:2018-04-09 06:59:29

标签: angular angular5 angular-changedetection

我非常了解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');
    }
  }
}
  • 在上面的示例中,我设置了@Input属性ngModel和指令的模型对象更改的订阅。模型值更改时,应在控制台中记录更改。

#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');
}
  • 我在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()时立即更改检测?

非常感谢先进!!

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

::干杯::

约瑟普布罗兹

1 个答案:

答案 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(指令)没有在正确的时刻发现变化。

对不起家伙,但我希望这个订阅检测更改的例子能帮助别人!!

::干杯::

约瑟普布罗兹