2 个组件之间的 2 种方式绑定仅适用于第一个字母

2 way binding between 2 components works only on first letter

我遇到了一个非常严重的 运行ge 错误,我已经研究过了,但我很难弄清楚。我发现的大多数相似项目在最终更改前大约已有一年的历史,现在无法使用。

错误信息

Expression has changed after it was checked. Previous value: 'Angular2'. Current value: 'Angular2x'.

出于某种原因,当它以 2 种方式绑定到 属性 时抛出异常。

我认为错误发生在以下代码运行之后。

  ngDoCheck(){
    this.bindingPropertyChange.emit(this.bindingProperty)
  }

我创建了一个 Plunker 来重现错误。 Plunker here

有人知道为什么会这样吗?如果是这样,您能解释一下为什么抛出这个异常吗?

我不是说 ngDoCheck 的合适人选,但 ngDoCheck[ 似乎有问题=28=]。其他人可以提出建议,并且可以编辑我的答案以说明有关 ngDoCheck.

的任何内容

但截至目前,您可以使用 keyup 事件并将函数与其绑定,如下所示,

演示 : https://plnkr.co/edit/hSrPuWNyJd6Az8sHXh1T?p=preview

<input [(ngModel)]="bindingProperty" (keyup)="check()" class="form-control"/>

check(){
    this.bindingPropertyChange.emit(this.bindingProperty)
}

ngDoCheck 是你的问题,原因如下:

ngDoCheck 会在您的模型内部发生变化后触发。

在您输入字母后,angular 开始检查所有地方(整个应用程序)是否有任何相关更改,Angular 运行仅在更改后进行一次更改检测,之后应该不会有任何更新。(单向数据流,仅一次检查)。

假设更改检测 运行 ( ngDoCheck ) 成功并相应地更新了 UI,但是在检查过程中,您突然进行了另一个更改。

开发模式 中,Angular2 运行 在第一个之后进行另一个更改检测,以确保在第一个之后没有任何更改,并且因为你发射了那个事件并再次默默地改变了模型,angular 生气并抛出错误。

但是,在 Prod 模式 中,Angular 不会 运行 第二次检查,因此您不会在生产中看到此错误,但是您的模型更新 ( emit ) 不会反映在 UI 中。(要对此进行测试,只需将 ngCore.enableProdMode(); 添加到您的 main.ts 文件中,错误就会消失)。

这里有几种方法可以解决这个问题:

1- 改变你的策略,就像在我的 First Plunker 中,你可以简单地使用对象绑定并绕过这个问题。

2- 使用 setTimeout 推迟您的更改,这将 运行 另一个更改检测并使 angular 高兴:

ngDoCheck(){
    setTimeout(()=>{
      this.bindingPropertyChange.emit(this.bindingProperty)
    });

  }

这里是 plunker

3- 不要使用 ngDoCheck 并使用 (input) 或 (keyup) 或类似事件在另一个循环中发出您的更改,这再次使 Angular 到 运行 另一个更改检测:

注意 我建议使用 (input) 而不是 keyup 或 keydown 或类似的,原因是如果你使用 keyup/keydown ,更新将不会是无缝的,因为如果你按下一个键并按住它,直到你释放键,更新才会发生,但是使用 (input) ,它会立即发生,就像你在评论中说的那样,如果用户要用鼠标复制粘贴他们是不使用键,它不会更新模型。

<input [(ngModel)]="bindingProperty" (input)="emitUp()" class="form-control"/>

emitUp(){
    this.bindingPropertyChange.emit(this.bindingProperty)
  }

这是Plunker