我的范围中有一个对象数组,我想要观察每个对象的所有值 .
这是我的代码:
function TodoCtrl($scope) {
$scope.columns = [
{ field:'title', displayName: 'TITLE'},
{ field: 'content', displayName: 'CONTENT' }
];
$scope.$watch('columns', function(newVal) {
alert('columns changed');
});
}
但是当我修改这些值时,例如我将 TITLE
更改为 TITLE2
, alert('columns changed')
从未弹出 .
如何深入观察数组内的对象?
有一个现场演示:http://jsfiddle.net/SYx9b/
10 回答
您可以将
$watch
的第3个参数设置为true
:见https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch
从Angular 1.1.x开始,您还可以使用$ watchCollection来观看浅表(只是“第一级”)的集合 .
见https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchCollection
在你的$ watch中深度潜水物体会产生性能影响 . 有时(例如,当更改只是推送和弹出时),您可能希望$观察一个容易计算的值,例如array.length .
如果你只想看一个数组,你可以简单地使用这段代码:
example
但这不适用于多个数组:
example
为了处理这种情况,我通常将我想要观看的多个数组转换为JSON:
example
正如@jssebastian在评论中指出的那样,
JSON.stringify
可能比angular.toJson
更可取,因为它可以处理以'$'开头的成员以及其他可能的情况 .值得注意的是,在Angular 1.1.x及更高版本中,您现在可以使用$watchCollection而不是$ watch . 虽然$ watchCollection似乎创建了浅表,但它不能像你期望的那样使用对象数组 . 它可以检测数组的添加和删除,但不能检测数组内对象的属性 .
$watchCollection 完成你想做的事 . 以下是从angularjs网站http://docs.angularjs.org/api/ng/type/$rootScope.Scope复制的示例 . 虽然方便,但需要考虑性能,尤其是在观看大型集合时 .
以下是使用示例观察范围变量的3种方法的比较:
$watch() 由以下方式触发:
$watchCollection() 由以上所有内容触发:
$watch(..., true) 由以上所有内容触发AND:
JUST ONE MORE THING...
$watch() 是唯一一个在用另一个数组替换数组时触发的,即使该另一个数组具有相同的确切内容 .
例如,
$watch()
会触发,而$watchCollection()
则不会:下面是一个示例JSFiddle的链接,它使用所有不同的监视组合并输出日志消息来指示触发了哪些“监视”:
http://jsfiddle.net/luisperezphd/2zj9k872/
这个解决方案对我很有用,我在一个指令中这样做:
范围 . $ watch(attrs.testWatch,function(),true);
真实的工作做得很好,并对所有的chnages做出反应(添加,删除或修改字段) .
这是一个可以玩它的工作的plunker .
Deeply Watching an Array in AngularJS
我希望这对你有用 . 如果您有任何疑问,请随时提问,我会尽力帮助:)
在我的情况下,我需要观看一个服务,其中包含一个地址对象,也由其他几个控制器监视 . 我被困在一个循环中,直到我添加了'true'参数,这似乎是观看对象时成功的关键 .
设置
$watch
函数的objectEquality
参数(第三个参数)绝对是观察数组所有属性的正确方法 .Piran回答得很好,并提到
$watchCollection
.More Detail
我回答一个已经回答的问题的原因是因为我想指出_604458的答案不是很好,不应该使用 .
问题是摘要不会立即发生 . 他们必须等到当前的代码块完成才能执行 . 因此,观察一个数组的
length
实际上可能会错过$watchCollection
将捕获的一些重要更改 .假设这个配置:
乍一看,似乎这些会同时发射,例如在这种情况下:
这很好用,但考虑一下:
请注意,即使数组有一个新元素并且丢失了一个元素,结果长度也是相同的,所以就像
$watch
一样关注时,length
没有改变 . 不过,$watchCollection
已经接受了 .同一个块中的push和pop也会出现相同的结果 .
Conclusion
要观察数组中的每个属性,请在数组iteself上使用包含第三个参数(objectEquality)的
$watch
并设置为true . 是的,这很昂贵,但有时是必要的 .要观察对象何时进入/退出数组,请使用
$watchCollection
.不要在数组的
length
属性上使用$watch
. 我几乎没有理由这样做 .