为什么*更改EventEmitter侦听器在Angular中发出两次(自定义双向数据绑定属性)?

时间:2018-03-29 06:17:47

标签: angular

以下是如何在Angular中创建双向数据绑定的方法:https://blog.thoughtram.io/angular/2016/10/13/two-way-data-binding-in-angular-2.html#creating-custom-two-way-data-bindings

例如,我在组件中创建了counter双向数据绑定属性。有用。现在,我还希望获得有关使用组件的counterChange输出更改属性的通知。

以下是组件的代码:

export class CustomCounterComponent {

  counterValue = 0;
  @Output() counterChange = new EventEmitter();

  @Input()
  get counter() {
    return this.counterValue;
  }

  set counter(val) {
    this.counterValue = val;
    this.counterChange.emit(this.counterValue);
  }

  decrement() {
    this.counter--;
  }

  increment() {
    this.counter++;
  }
}

以下是我如何使用它:

@Component({
  selector: 'my-app',
  template: `
    <custom-counter [(counter)]="counterValue" (counterChange)="onChange($event)"></custom-counter>
    <p><code>counterValue = {{counterValue}}</code></p>
  `
})
export class AppComponent {
  onChange(value) {
    console.log('onChange!', value)
  }
  counterValue = 5;
}

所需行为:我希望在值发生变化时调用onChange一次。

特定问题:每次值更改时,都会调用onChange两次。

有什么想法被称为2次?

另外,我有一个完整的例子:https://plnkr.co/edit/8HGXNhhYQRoLVJeDlqWK?p=preview。只需打开控制台即可查看。

1 个答案:

答案 0 :(得分:2)

修改

在进一步挖掘之后,我发现了真正的问题。

如果您使用set counter方法设置断点并点击+按钮,您将会看到它并触发两次。这就是为什么,它会发出两次事件,onChange方法会被调用两次。

此外,我检查了调用堆栈,并查看调用set counter的位置。

第一个,正如您所怀疑的那样是this.counter++

看看第二个

Source

当您更改counter时,它会触发角度和角度调用中的更改检测

.counter = currVal_2

再次触发set counter

所以,我将this.counterChange.emit(this.counterValue);set counter移到decrementincrement方法内部。

  set counter() {
    return this.counterValue;
  }

  @Input()
  set counter(val) {
    this.counterValue = val;
  }

  decrement() {
    this.counter--;
    this.counterChange.emit(this.counterValue);
  }

  increment() {
    this.counter++;
    this.counterChange.emit(this.counterValue);
  }

看看this

---------陈旧(部分错误)答案-------------

因为您已经在使用双向绑定并自己绑定该方法。

[(counter)]="counterValue"[counter]="counterValue" (counterChange)="counterValue = $event"的糖语法。因此,如果您想使用自定义counterChange方法,只需从()删除[(counter)]="counterValue"

有关详细信息,请take a look at the docs

所以,改变

<custom-counter [(counter)]="counterValue" (counterChange)="onChange($event)"></custom-counter>

<custom-counter [counter]="counterValue" (counterChange)="onChange($event)"></custom-counter>

您也可以删除(counterChange)="onChange($event)"

试试这个,

<custom-counter [(counter)]="counterValue"></custom-counter>