AngularJS - 重置$ scope.value不会更改模板中的值(随机行为)

时间:2012-08-29 11:31:40

标签: angularjs

看看http://jsfiddle.net/2NJ7y/3/(AngularJS 1.0.1版本)上的示例。有一个简单的应用程序,正在等待输入幸运数字。如果数字等于7,我将幸运数字重置为空。如果我多次输入数字7,有时/随机的幸运数字会保留在输入字段中。为什么?这种行为如何解决?感谢。

3 个答案:

答案 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;
    }
})

Fiddle

@Valentyn的另一个SO answer让我想到尝试解决这个问题。

答案 2 :(得分:1)

如果你只是把

$scope.luckynumber = undefined;

在警报之前你没有消除竞争条件,但你确实改变它以便7被正确清除,但有时你会得到警报两次。

如果警报代码被幂等的东西替换,比如改变DOM以显示错误,那么这个问题就不那么重要了。