3

小提琴

我有一个列表,我希望在它发生变化时得到通知。一个简单的$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'每次调用时都会调用 for 的回调names.push()。是否有为此推荐的解决方法?或者我只是没有$watch正确使用?

4

2 回答 2

9

您是对的,出于性能原因,默认情况下进行角度检查以供参考。引用与相等的使用取决于 $watch 函数的第三个参数的值,如您在 docs中所见。只需将其设置为 true(默认情况下为 false),您的小提琴就可以工作了 -就在这里,工作正常。

改变:

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

编辑 - 性能影响:

根据变量的大小和复杂性,比较两个数组/对象的效率显然非常低(因此默认情况下通过参考角度进行检查)。还有一种替代方法——观察数组的长度。这有明显的局限性——改变一个元素不再触发 $watch 功能——但可以非常快。这是一个更新的小提琴

于 2012-12-11T23:05:23.233 回答
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/如果您正在处理大量数据,此散列方法也可以更新为错误响应式(例如仅每隔 2 或 3 个字符散列)

于 2012-12-13T20:58:32.567 回答