设置$watch函数的objectEquality参数(第三个参数)绝对是监视数组所有属性的正确方法。
$scope.$watch('columns', function(newVal) {
alert('columns changed');
},true); // <- Right here
Piran很好地回答了这个问题,并提到了$watchCollection。
更详细地
我之所以要回答一个已经回答过的问题,是因为我想指出wizardwerdna的答案不是一个好的答案,不应该被使用。
问题是,摘要不会立即发生。它们必须等到当前代码块完成后才能执行。因此,观察数组的长度实际上可能会错过$watchCollection将捕捉到的一些重要更改。
假设如下配置:
$scope.testArray = [
{val:1},
{val:2}
];
$scope.$watch('testArray.length', function(newLength, oldLength) {
console.log('length changed: ', oldLength, ' -> ', newLength);
});
$scope.$watchCollection('testArray', function(newArray) {
console.log('testArray changed');
});
乍一看,这些似乎会同时发射,比如在这个例子中:
function pushToArray() {
$scope.testArray.push({val:3});
}
pushToArray();
// Console output
// length changed: 2 -> 3
// testArray changed
这很好,但考虑一下:
function spliceArray() {
// Starting at index 1, remove 1 item, then push {val: 3}.
$testArray.splice(1, 1, {val: 3});
}
spliceArray();
// Console output
// testArray changed
请注意,即使数组有一个新元素和丢失了一个元素,结果的长度是相同的,因此对于$watch而言,长度没有改变。不过$watchCollection发现了它。
function pushPopArray() {
$testArray.push({val: 3});
$testArray.pop();
}
pushPopArray();
// Console output
// testArray change
同样的结果也发生在同一个块的push和pop操作中。
结论
要观察数组中的每个属性,在数组本身上使用$watch,其中包括第三个参数(objectEquality)并将其设置为true。是的,这很昂贵,但有时是必要的。
要观察对象何时进入/退出数组,使用$watchCollection。
不要在数组的length属性上使用$watch。我几乎想不出有什么好的理由这样做。