AngularJS:$watch不会因对象数组的更改而被触发

Posted

技术标签:

【中文标题】AngularJS:$watch不会因对象数组的更改而被触发【英文标题】:AngularJS: $watch not being triggered for changes to an array of objects 【发布时间】:2013-03-21 05:16:52 【问题描述】:

我有一个表,用户可以选择根据某些列和这些列的某些值来过滤表中的行。跟踪此过滤器的对象结构如下所示:

$scope.activeFilterAttributes = [
    
        "columnName": "city",
        "values": ["LA", "OT", "NY"]
    ,
    
        "columnName": "weather",
        "values": ["humid", "sunny"]
    
];

所以数组中的对象包含“columnName”和“values”键。 “columnName”表示要为过滤器考虑的列,而“values”包含过滤器值。基本上,上面的数组将导致表中的行包含城市列包含“LA”、“OT”或“NY”作为值,而天气列包含“潮湿”或“晴天”作为值。不显示不包含这些值的其他行。

为了帮助更好地理解这个对象,如果用户希望只查看“城市”列中包含“LA”或“NY”的行,则结果数组将如下所示:

$scope.activeFilterAttributes = [
    
        "columnName": "city",
        "values": ["LA", "NY"]
    ,
    
        "columnName": "weather",
        "values": []
    
];

用户设置或删除这些过滤器。每当发生这种情况时,都会更新上述数组。 此更新正确发生并且我已经验证了它 - 这里没有问题。

问题在于 $watch()。我有以下代码:

$scope.$watch('activeFilterAttributes', function() 
    //Code that should update the rows displayed in the table based on the filter

虽然$scope.activeFilterAttributes 会随着用户更新 UI 中的过滤器而正确更新,但更新时不会触发 $watch。当应用程序第一次加载时触发,但以后的更新对此没有影响。

我创建了一个小提琴来证明这一点:http://jsfiddle.net/nCHQV/

在fiddle中,$scope.info代表表格的行,可以这么说;$scope.data代表过滤器。 单击按钮相当于更新过滤器(在小提琴的情况下 - 数据),从而更新表中显示的行(在小提琴的情况下 - 信息)。但是可以看出,单击按钮时信息不会更新。

对象数组发生变化时不应该触发$scope.$watch吗?

【问题讨论】:

【参考方案1】:

$watch 方法采用名为objectEquality 的可选第三个参数,用于检查两个对象是否相等,而不仅仅是共享相同的引用。这不是默认行为,因为它是比参考检查更昂贵的操作。您的手表没有被触发,因为它仍然指向同一个对象。

请参阅docs 了解更多信息。

$scope.$watch('activeFilterAttributes', function() 
  // ...
, true); // <-- objectEquality

添加该参数,一切都很好。

【讨论】:

谢谢乔希 - 我不记得你为问题的原因和解决方案提供了多少次了不起的解释。非常感谢。顺便说一句 - 我正在为***.com/questions/15316363/… 中提供的问题测试你的另一个很棒的解决方案 - 到目前为止,它可以满足我的期望,并且在经过更多测试后很快会将其标记为正确答案。 感谢您的好意——很高兴我能帮上忙! @JoshDavidMiller,感谢您的精彩解释。正如您所说,这是一项昂贵的操作,请您告诉我们如何避免使用第三个参数的情况。 呵呵,我把它简化为一个复选框,但我的实现就是这样,一个使用 ios 样式 btn-switch 的滑动按钮。但是,我明白你所说的 Angular 是什么意思。我可以做任何一种实现,控制器和模型没有改变,只是我的模板发生了变化。谢谢@JoshDavidMiller。 触摸。再次感谢您的帮助。 Angular 非常酷,2 向绑定和干净的分离令人惊叹。但是学习曲线太糟糕了!【参考方案2】:

现在接受的答案有点过时了为真。

所以这个新功能现在在大多数情况下更可取。

查看this article 了解$watch 函数之间的更详细区别

【讨论】:

以上是关于AngularJS:$watch不会因对象数组的更改而被触发的主要内容,如果未能解决你的问题,请参考以下文章

第一次更新后,AngularJS $watch 数组失败

AngularJS - Watch 监听对象

angularjs中使用$scope.$watch监控对象模型的变化

vue.js $watch 对象数组

angularJS 里的$watch的用法

angularJS之$watch的一个小介绍