如何$监视列表的更改?

时间:2012-12-11 22:39:29

标签: javascript angularjs

fiddle

我有一个列表,我希望每当它发生变化时都会收到通知。一个简单的$watch表达式不起作用,我猜测是因为angular正在检查引用相等,而不是结构相等。

<html ng-app>
    <head>
    </head>
    <body ng-controller="Root">
        <h1>Base Angular Fiddle</h1>
        Times changed: {{timesChanged}}
        <ul>
            <li ng-repeat="name in names">{{name}}</li>
            <li><button ng-click="names.push('another name')">Add</button></li>
        </ul>
    </body>
</html>
​

​function Root($scope) {
    $scope.timesChanged = 0;
    $scope.names = ['foo', 'bar', 'baz'];
    $scope.$watch('names', function() {
        $scope.timesChanged++;
    });
}​

我希望会发生的是每次调用'names'时都会调用names.push()的回调。是否有针对此推荐的解决方法?或者我只是没有正确使用$watch

2 个答案:

答案 0 :(得分:9)

出于性能原因,您是对的,默认情况下进行角度检查以供参考。参考vs等式的使用取决于$ watch函数的第三个参数的值,正如您可以看到in the docs。只需将其设置为true(默认情况下为false)并且您的小提琴将起作用 - here it is, working.

改变:

$scope.$watch('names', function() {
        $scope.timesChanged++;
    }, true);

编辑 - 性能影响:

根据变量的大小和复杂程度,比较两个数组/对象显然效率非常低(因此默认情况下通过引用角进行检查)。还有一种方法 - 观察阵列的长度。这有明显的局限性 - 改变一个元素不再触发$ watch函数 - 但可以非常快。这是一个updated fiddle

答案 1 :(得分:1)

快速添加:

如果您想观看更多特殊的内容,可以这样做:

$scope.$watch(function() {
    // Define what you are watching for
    // For example convert your array into a string
    return String($scope.names);
}, function(newValue, oldValue) {
    // Do something cool.
});

这绝对没有names.length那么快,但你可以玩,找到一个复杂的解决方案。

如果有人感兴趣我使用修改后的Duff设备进行了快速哈希操作:http://jsfiddle.net/flek/mfKT6/1/如果您正在处理大量数据,则此哈希方法也可以更新为错误响应(如只有哈希值第二或第三个字符)