$ watch未在阵列更改时触发

时间:2013-03-12 13:58:58

标签: angularjs angularjs-scope

我试图找出为什么我的$watch没有被触发。这是相关控制器的片段:

$scope.$watch('tasks', function (newValue, oldValue) {
    //do some stuff
    //only enters here once
    //newValue and oldValue are equal at that point
});

$scope.tasks = tasksService.tasks();

$scope.addTask = function (taskCreationString) {
    tasksService.addTask(taskCreationString);//modifies tasks array
};

在我看来,tasks显然正在正确更新,因为我的长度是这样的:

<span>There are {{tasks.length}} total tasks</span>

我错过了什么?

4 个答案:

答案 0 :(得分:135)

尝试$watch('tasks.length', ...)$watch('tasks', function(...) { ... }, true)

默认情况下,$watch不检查对象是否相等,只是为了参考。因此,$watch('tasks', ...)将始终只返回相同的数组引用,而不会更改。

更新:Angular v1.1.4添加了$watchCollection()方法来处理这种情况:

  

Shallow监视对象的属性,并在任何属性发生变化时触发(对于数组,这意味着要观察数组项,对于对象映射,这意味着要观察属性)。如果检测到更改,则会触发listener回调。

答案 1 :(得分:13)

@Mark非常好的回答。除了他的答案之外,还应该注意$watch函数的一个重要功能。

使用$watch函数声明如下:

$watch(watch_expression, listener, objectEquality)

$watch 侦听器函数仅在当前监视表达式(在您的情况下为'tasks')中的值时调用之前对观察表达式的调用并不相同。 Angular保存对象的值以供以后比较。因此,观看复杂的选项将会产生不利的内存和性能影响。基本上,更简单的监视表达式值更好。

答案 2 :(得分:5)

我建议尝试

$scope.$watch('tasks | json', ...)

这将捕获tasks数组的所有更改,因为它将序列化数组作为字符串进行比较。

答案 3 :(得分:3)

对于一维数组,您可以使用$watchCollection

$scope.names = ['igor', 'matias', 'misko', 'james'];
$scope.dataCount = 4;

$scope.$watchCollection('names', function(newNames, oldNames) {
  $scope.dataCount = newNames.length;
});