当侦听器是Date()函数时,Angular watcher不起作用

时间:2013-01-09 12:34:12

标签: angularjs

我知道我问的是一个回答非常简单的问题(我是棱角分明的新人,在这里问这个问题确实需要很大的勇气;)。我有一个指令显示这样的时间:

Application.Directives
.directive('theClock', function(){
    return {
        retrict: 'EA',
        templateUrl: 'partials/partial.clock.html',
        link: function(scope, elem, attrs) {

            scope.dTime = Date();
            scope.$watch( function(scp){ return Date(); }, function(newVal){ 

                    scope.dTime = newVal;
                }
            );
        }
    };
});

我希望时间会更新每个$ digest周期,但事实并非如此。我知道使用setInterval ot $timeout是另一种方法,但我真的不想要一个时钟,我想知道为什么更新不会发生。顺便说一句,我在检查$apply()之后打电话给$$phase - 没有帮助

谢谢。

2 个答案:

答案 0 :(得分:5)

$ watch函数默认按引用比较对象,对于字符串/数字值更快更好,但不适用于像Date这样的复杂对象 - 日期可能会改变,但它总是相同的Date对象,所以引用不会改变。

这是为了避免在巨大阵列上进行严重的等式测试。

现在,虽然这可能有用(注意$ watch函数的第三个参数设置为true):

scope.dTime = new Date();
scope.$watch( function(scp){ return new Date(); }, function(newVal){ 

  scope.dTime = newVal;
  }, true
);

每次轮询$ watch函数(意味着每个应用程序周期)时,它可能会触发更改事件。

如果你想要if每秒触发,请从Date()返回秒数,返回类似于返回Math.floor(new Date()。valueOf()/ 1000)。然后根据需要设置dTime。

<强>更新

虽然angular的检查适用于return Date(),但问题是由于angular的脏检查系统 - 它只会在模型上触发更改时检查$ watch函数(意味着在$ scope中定义的模型) )。

这个来自Valentyn Shybanov的Plnkr可以作为一个例子 - 时钟函数触发模型上的变化,并且该变化触发$ watch函数。

ALSO ,请注意使用window.setTimeout的this version。它只能使用$ apply方法通知angularJS发生了更改。

答案 1 :(得分:2)

  

“我想了解为什么更新不会发生。”

我认为这张照片(来自Conceptual Overview page)最能说明:

Angular event loop

除非调用$ apply(),否则不会检查$ watch列表。 $ apply是我们进入“$ digest循环”的方式。许多(所有?)Angular内置指令自动调用$ apply(所以我们没有)。例如,正如@Tiago已经提到的,更改绑定的$ scope属性(在Angular内)将导致$ apply被调用。我们也可以自己明确地调用$ apply(例如,从我们定义的第三方库回调函数内部 - 如果我们不在这里调用$ apply,我们将不会进入$ digest循环)。

底线:除非我们进入蓝框(“Angular执行上下文”),否则不会检查$ watch列表 - 因此不会执行脏检查。