$watch 中的角度表达式触发两次 [英] Angular expressions in $watch trigger twice

查看:32
本文介绍了$watch 中的角度表达式触发两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Why does this $watch fire twice when a simple comparison is passed as the watchExpression?

$scope.foo = 0;  // simple counter

$scope.$watch('foo > 4', function() {
  console.log("foo is greater than 4: ", $scope.foo);
});

当页面加载时监听器触发,当 foo0 时,然后当 foo 的值再次(并且仅一次)> 超过 4.

The listener fires when the page loads, when foo is 0, then once more (and only once more) when the value of foo goes above 4.

为什么在页面加载时监听器会触发?当 foo 大于 4 时,为什么它不继续触发?

Why does the listener fire when the page loads? And why doesn't it continue to fire when foo is greater than 4?

我设置了一个简单的 plunkr 来显示发生了什么:http://plnkr.co/edit/ghYRl9?p=预览

I set up a simple plunkr to show what's happening: http://plnkr.co/edit/ghYRl9?p=preview

推荐答案

重读 Angular $watch docs 几次,我想我明白发生了什么.

After re-reading the Angular $watch docs a few more times, I think I understand what's happening.

仅当当前 watchExpression 的值与上一次调用 watchExpression 的值不相等时才调用监听器

The listener is called only when the value from the current watchExpression and the previous call to watchExpression are not equal

Angular 跟踪 watchExpression 的值 foo >4 与每个 digest() 循环.因为这在 foo 大于 4 之前评估为 false,所以侦听器不会触发.同样,在 foo 大于 4 之后,Angular 比较的值都为真.它检测到变化的唯一时间是计算表达式交叉时.

Angular tracks the value of the watchExpression foo > 4 with each digest() loop. Because this evaluated to false until foo was greater than 4, the listener didn't fire. Likewise, after foo was greater than 4, the values Angular was comparing were both true. The only time it detected a change was when the evaluated expression crossed over.

两个值传递给 $watch 侦听器函数,新值和旧值.记录这些值表明正在评估 watchExpression,而 Angular 正在寻找这些值的变化.

Two values are passed to the $watch listener function, the new value and the old one. Logging these values shows that the watchExpression is being evaluated, and Angular is looking for a change in those values.

$scope.$watch('foo > 4', function(newVal, oldVal) {
  console.log("foo is greater than 4: ", $scope.foo, oldVal, newVal);
});

// foo is greater than 4:  5 true false

还记录了在页面加载时调用侦听器的原因:

The reason the listener was called on page load is also documented:

在观察者注册到作用域后,listener fn 被异步调用(通过 $evalAsync)来初始化观察者.在极少数情况下,这是不可取的,因为当 watchExpression 的结果没有改变时会调用侦听器.要在 listener fn 中检测这种情况,您可以比较 newValoldVal.如果这两个值相同 (===),则由于初始化而调用了侦听器.

After a watcher is registered with the scope, the listener fn is called asynchronously (via $evalAsync) to initialize the watcher. In rare cases, this is undesirable because the listener is called when the result of watchExpression didn't change. To detect this scenario within the listener fn, you can compare the newVal and oldVal. If these two values are identical (===) then the listener was called due to initialization.

我用第二个 $watch 更新了 plunkr 来评估foo 内部:

I updated the plunkr with a second $watch that evaluates the value of foo internally:

$scope.$watch('foo', function(newVal, oldVal) {
  if ($scope.foo > 4) {
  console.log("foo is greater than 4: ", $scope.foo, newVal, oldVal);
  }
});

// foo is greater than 4:  5 5 4
// foo is greater than 4:  6 6 5
// foo is greater than 4:  7 7 6

这篇关于$watch 中的角度表达式触发两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆