$ watch监听器被调用一次而不改变表达式

时间:2014-01-14 20:18:04

标签: javascript angularjs angularjs-scope

在我的控制器中,我有一个名为datetime的变量,它每秒都会被一个计时器更新。当白天改变时我需要做一些工作,所以我注册了以下观察者:

$scope.$watch("datetime | date: 'MM/dd/yyyy'", function (newDate, oldDate) {
    console.log(newDate === oldDate);
}, true);

但是在执行开始时调用此侦听器时newDate等于oldDate。有谁知道会发生什么?更改datetime的代码如下:

var timeoutId;

function startTimer() {
    timeoutId = $timeout(tick, 1000);
    timeoutId.then(startTimer);
}

function stopTimer() {
    $timeout.cancel(timeoutId);
    timeoutId = undefined;
}

function tick() {
    $scope.datetime = new Date();
}

$scope.init = function () {
    startTimer();
}

$scope.init()ng-init调用。

2 个答案:

答案 0 :(得分:4)

来自 the docs (强调我的):

  

只有当前watchExpression的值和之前对watchExpression的调用不相等时才会调用侦听器(除了初始运行,见下文)。
  [...]
  在观察者注册观察者之后,异步调用侦听器fn(通过$ evalAsync)来初始化观察者。在极少数情况下,这是不可取的,因为当watchExpression的结果没有改变时,监听器被称为 。要在侦听器fn中检测此场景,您可以比较newVal和oldVal。如果这两个值相同(===)则由于初始化而调用了监听器。

所以,改变你的$watch就像这样:

$scope.$watch("datetime | date: 'MM/dd/yyyy'", function (newDate, oldDate) {
    if (newData !== oldDate) {
        /* Value has changed: Do something useful */
        console.log(newDate === oldDate);
    }
}, true);

答案 1 :(得分:1)

$ watch在初始加载期间触发,使用标志来避免它。

var first = true;
$scope.$watch("datetime | date: 'MM/dd/yyyy'", function (newDate, oldDate) {
    if(!first){
       console.log(newDate === oldDate);
    } else {
        first = false;
    }
}, true);