看看http://jsfiddle.net/2NJ7y/3/(AngularJS 1.0.1版本)上的示例。有一个简单的应用程序,正在等待输入幸运数字。如果数字等于7,我将幸运数字重置为空。如果我多次输入数字7,有时/随机的幸运数字会保留在输入字段中。为什么?这种行为如何解决?感谢。
答案 0 :(得分:6)
我做了一些调试。
首先,对于我来说,幸运数字不是随机存在于输入字段中。
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才会保留在输入字段中。
会发生什么:当您输入由listener function input directive处理的7个已触发输入事件时。监听器函数调用$setViewValue。 $ setViewValue设置$ viewValue,$ modelValue,模型值并调用$ viewChangeListeners(ngChangeDirective simply adds handler到$ viewChangeListeners)。显示警报,luckynumber设置为null。毕竟,如果luckynumber与以前的脏检查$watch handler之前的值不同,那么$render就会被调用。
在我的示例中,如果先前的模型值为“3”或“”,则调用$ render。如果之前的模型值为null,则不会调用$ render。
为什么带有0延迟的$ timeout工作:当你使用0延迟函数调用$ timeout并将luckynumber更改为null时,会在events queue结束时推迟(浏览器中的所有javascript执行在单个线程上)。 $ viewChangeListener不会将模型值从7更改为null。 $ digest结束。然后调用$ timeout处理程序。模型值设置为null。 $ watch handler和$ render被调用。 $ render将输入值设置为“”。
答案 1 :(得分:2)
最后,一个解决方案。使用$ watch代替ng-change:
$scope.$watch('luckynumber', function() {
if ($scope.luckynumber == 7) {
alert('The lucky number mustn\'t be equal 7.');
$scope.luckynumber = null;
}
})
@Valentyn的另一个SO answer让我想到尝试解决这个问题。
答案 2 :(得分:1)
如果你只是把
$scope.luckynumber = undefined;
在警报之前你没有消除竞争条件,但你确实改变它以便7被正确清除,但有时你会得到警报两次。
如果警报代码被幂等的东西替换,比如改变DOM以显示错误,那么这个问题就不那么重要了。