Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript $watch中的角度表达式触发两次_Javascript_Angularjs - Fatal编程技术网

Javascript $watch中的角度表达式触发两次

Javascript $watch中的角度表达式触发两次,javascript,angularjs,Javascript,Angularjs,当一个简单的比较作为watchExpression传递时,为什么这个$watch会触发两次 $scope.foo=0;//简易计数器 $scope.$watch('foo>4',function(){ log(“foo大于4:”,$scope.foo); }); 当页面加载时,当foo为0时,侦听器触发,然后当foo的值超过4时,再次(并且仅再次)触发 当页面加载时,为什么侦听器会启动?当foo大于4时,它为什么不继续发射 我设置了一个简单的plunkr来显示发生了什么:在重新阅读了几遍之后,

当一个简单的比较作为watchExpression传递时,为什么这个
$watch
会触发两次

$scope.foo=0;//简易计数器
$scope.$watch('foo>4',function(){
log(“foo大于4:”,$scope.foo);
});
当页面加载时,当
foo
0
时,侦听器触发,然后当
foo
的值超过4时,再次(并且仅再次)触发

当页面加载时,为什么侦听器会启动?当
foo
大于4时,它为什么不继续发射

我设置了一个简单的plunkr来显示发生了什么:

在重新阅读了几遍之后,我想我理解了发生了什么

仅当当前watchExpression和上一次调用watchExpression的值不相等时,才会调用侦听器

角度跟踪watchExpression
foo>4
与每个
digest()
循环的值。因为在
foo
大于4之前,该值的计算结果为false,所以侦听器没有启动。同样,在
foo
大于4后,所比较的角度值均为真。它检测到变化的唯一时间是当计算表达式交叉时

将两个值传递给
$watch
侦听器函数,即新值和旧值。记录这些值表明正在计算watchExpression,Angular正在查找这些值中的更改

$scope.$watch('foo>4',函数(newVal,oldVal){
log(“foo大于4:”,$scope.foo,oldVal,newVal);
});
//foo大于4:5对错
还记录了在页面加载时调用侦听器的原因:

在向作用域注册观察程序后,异步调用
侦听器
fn(通过
$evalAsync
)初始化观察程序。在极少数情况下,这是不可取的,因为在
watchExpression
的结果没有更改时调用侦听器。要在
侦听器中检测此场景
fn,可以比较
newVal
oldVal
。如果这两个值相同(
==
),则由于初始化而调用了侦听器

我用第二个
$watch
更新了,它在内部评估
foo
的值:

$scope.$watch('foo',函数(newVal,oldVal){
如果($scope.foo>4){
log(“foo大于4:”,$scope.foo,newVal,oldVal);
}
});
//foo大于4:5 4
//foo大于4:6.5
//foo大于4:7 6

为了补充这一点,我发现在
$watch
回调中计算特定条件(>4)总是更好(正如您在上一个代码片段中所做的那样),因为能够检查
$scope
属性是否实际有值(
newVal!=null
)以及它是否更改通常是很有价值的(
!angular.equals(newVal,oldVal)
)。正如特里所说,我用来检查$watch侦听器上的一个对象,以便它不会在init上多次触发:if(newVal!=null&(!angular.equals(newVal,oldVal)){console.log('object changed');}仅在初始加载后更新表单/对象时激发。请注意一点;请使用!==而不是!=JSLinters将感谢您。