数组更改时不触发$ watch

我想弄清楚为什么我的$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> 

我错过了什么?

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

默认情况下, $ watch不检查对象是否相等,仅供参考。 所以, $watch('tasks', ...)将总是简单地返回相同的数组引用,这是不变的。

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

浅层观察对象的属性,并在任何属性改变时触发(对于数组,这意味着要观看数组项,对于对象映射,这意味着要看属性)。 如果检测到更改,则会触发listenercallback。

非常好的@Mark答案。 除了他的回答,还有一个你应该注意的$watchfunction的重要function。

使用$watch函数声明如下:

 $watch(watch_expression, listener, objectEquality) 

$watch 监听器函数仅在当前监视expression式的值(在您的情况下为'tasks' )和先前对监视expression式的调用不相等时调用。 Angular保存对象的值以供以后比较。 因此,观看复杂的选项将具有不利的记忆和性能影响。 基本上越简单的手表performance值越好。

我会build议尝试

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

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

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

 $scope.names = ['igor', 'matias', 'misko', 'james']; $scope.dataCount = 4; $scope.$watchCollection('names', function(newNames, oldNames) { $scope.dataCount = newNames.length; });