我得到一个非常奇怪的错误,我已经研究过,我很难搞清楚。我发现的大多数项目都是在最终更改之前大约一年,现在不起作用。
错误消息
检查后表情发生了变化。之前的价值:' Angular2'。当前价值:' Angular2x'。
出于某种原因,当它以2路方式绑定到该属性时,它会抛出一个异常。
我认为在运行以下代码后会发生错误。
ngDoCheck(){
this.bindingPropertyChange.emit(this.bindingProperty)
}
我创建了一个Plunker来重现错误。 Plunker here
有谁知道为什么会这样?如果是这样,你能解释为什么抛出这个异常吗?
答案 0 :(得分:2)
ngDoCheck是你的问题,原因如下:
ngDoCheck会在模型内部发生变化后触发。
在您输入的字母后,angular开始检查任何地方(整个应用程序)是否有任何相关更改,Angular在更改后只运行一次更改检测,之后不应该有任何更新。(单向数据流,只检查一次。)
让我们说成功运行变更检测(ngDoCheck)并相应地更新UI,但在检查过程中,您突然进行了另一次更改。
在开发模式中,Angular2在第一个之后运行另一个changeDetection以确保在第一个之后没有任何变化,并且因为你发出了该事件并且再次无声地更改了模型,角度很生气抛出错误。
但是,在产品模式中,Angular不会运行第二次检查,因此您不会在生产中看到此错误,但您的模型更新(发布)不会反映在UI中。 (要对此进行测试,只需将ngCore.enableProdMode();
添加到main.ts
文件中,错误就会消失。
以下是解决这个问题的几种方法:
1-更改您的策略,例如在我的First Plunker中,您只需使用对象绑定并绕过问题。
2-使用setTimeout推迟你的更改,这将运行另一个更改检测并使角度快乐:
ngDoCheck(){
setTimeout(()=>{
this.bindingPropertyChange.emit(this.bindingProperty)
});
}
以下是plunker
3-不要使用ngDoCheck并使用(输入)或(keyup)或类似事件在另一个周期中发出更改,这再次使Angular运行另一个更改检测:
注意我建议使用(输入)over keyup或keydown或类似的,原因是如果你使用keyup / keydown,更新将不会无缝,因为如果你按一个键并保持在那里更新将不会发生,直到您释放密钥,但有(输入),它会立即发生,就像你在评论中说,如果用户要用鼠标复制粘贴他们没有使用密钥和它不会更新模型。
<input [(ngModel)]="bindingProperty" (input)="emitUp()" class="form-control"/>
emitUp(){
this.bindingPropertyChange.emit(this.bindingProperty)
}
以下是Plunker
答案 1 :(得分:1)
我不是对 ngDoCheck
说些什么的合适人选,但似乎 ngDoCheck
存在问题。其他人可以建议并且可以编辑我的答案,以便对 ngDoCheck
说些什么。
但截至目前,您可以使用 keyup
事件并使用它绑定一个函数,如下所示,
DEMO : https://plnkr.co/edit/hSrPuWNyJd6Az8sHXh1T?p=preview
<input [(ngModel)]="bindingProperty" (keyup)="check()" class="form-control"/>
check(){
this.bindingPropertyChange.emit(this.bindingProperty)
}