AngularJS:$ watch未被触发更改对象数组

use*_*187 18 angularjs

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

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "OT", "NY"]
    },
    {
        "columnName": "weather",
        "values": ["humid", "sunny"]
    }
];
Run Code Online (Sandbox Code Playgroud)

因此,数组中的对象包含"columnName"和"values"键."columnName"表示要为过滤器考虑的列,而"values"包含过滤器值.基本上,上面的数组将导致表中的行,其中city列包含"LA","OT"或"NY"作为值,而weather列包含"湿"或"晴天"作为值.不显示不包含这些值的其他行.

为了更好地理解这个对象,如果用户只希望在"city"列中看到那些"LA"或"NY"的行,则结果数组将如下所示:

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "NY"]
    },
    {
        "columnName": "weather",
        "values": []
    }
];
Run Code Online (Sandbox Code Playgroud)

用户设置或删除这些过滤器.只要发生这种情况,就会更新上面的数组.此更新正确发生,我已经验证了 - 这里没问题.

问题出在$ watch()上.我有以下代码:

$scope.$watch('activeFilterAttributes', function() {
    //Code that should update the rows displayed in the table based on the filter
}}
Run Code Online (Sandbox Code Playgroud)

$scope.activeFilterAttributes用户在UI中更新过滤器时,会正确更新,但在更新时不会触发$ watch.它是在应用程序加载时第一次触发但未来的更新对此没有影响.

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

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

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

Jos*_*ler 66

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

有关详细信息,请参阅文档.

$scope.$watch('activeFilterAttributes', function() {
  // ...
}, true); // <-- objectEquality
Run Code Online (Sandbox Code Playgroud)

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


Ami*_*ble 5

现在接受的答案有点过时,因为AngularJS 1.1.4 $WatchCollection添加了函数以用于数组和其他集合,这比$Watch深度相等标志设置为true的成本要便宜得多.

所以这个新功能现在在大多数情况下都是可取的.

有关函数之间更详细的差异,请参阅此文章$watch