看看http://jsfiddle.net/2NJ7y/3/(AngularJS 1.0.1版本)。有一个简单的应用程序,它正在等待幸运数字的输入。如果数字等于7,我将幸运数字重置为空。如果我多次输入数字7,有时/随机的幸运数字会留在输入字段中。为什么?这种行为是如何解决的?谢谢
我已经做了一些调试。
首先,对我来说,幸运数字不是随机出现在输入框中的。
enter 3 (model==3, input==3)
=>enter 7 (alert, model==null, input="")
=>enter 3 (model==3, input==3)
=>remove 3 (model=="", input=="")
=>enter 7 (alert, model==null, input="")
=>enter 7 (alert, model==null, input="7")
7仅当先前的模型值为空时才保留在输入字段中。
发生了什么:当您输入7激发的输入事件时,该事件由input指令的侦听器函数处理。侦听器函数调用$setViewValue$setViewValue设置$viewValue、$modelValue、模型值并调用$viewChangeListeners(ngChangeDirective只是将处理程序添加到$viewChangeListers)。显示警报,幸运数字设置为空。毕竟,如果luckynumber与之前脏检查中的上一个值不同,则调用$watchhandler和$render。
在我的示例中,如果以前的模型值为"3"或",则调用$render。如果以前的模型值为null,则不调用$render。
为什么$timeout with 0 delay有效:当您调用$timeout with0 delay函数,并将luckynumber更改为null时,它会延迟到事件队列的末尾(浏览器中的所有javascript都在单个线程上执行)$viewChangeListener没有将模型值从7更改为null$摘要结束。然后调用$timeout处理程序。模型值设置为null$调用watchhandler和$render$render将输入值设置为"。
终于有了一个解决方案。使用$watch而不是ng-change:
$scope.$watch('luckynumber', function() {
if ($scope.luckynumber == 7) {
alert('The lucky number mustn't be equal 7.');
$scope.luckynumber = null;
}
})
Fiddle。
@Valentyn的另一个SO回答让我想到了尝试这个问题的解决方案。
如果您只需放置
$scope.luckynumber = undefined;
在发出警报之前,你没有消除比赛条件,但你确实改变了它,使7确实被正确清除,但有时你会收到两次警报。
如果警报代码被幂等的东西替换,比如更改DOM以显示错误,那么这个问题就不重要了。