我试图找出为什么我的$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>
我错过了什么?
答案 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;
});