AngularJS $ watchCollection与ng-repeat结合使用

时间:2015-01-06 16:20:18

标签: javascript angularjs angularjs-ng-repeat

如果直接在ng-repeat中使用输入字段,我在列表中的更改中收到通知会有一些问题。否则我可以更改值并从$ watchCollection获取通知。

简化示例:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.js">
    </script>
</head>
<body>
    <section ng-app="myApp" ng-controller = "TestController">
        <button ng-click = "pushToList()">Add number to list.</button>
        <button ng-click = "changeFirstElement()">Change first element.</button>
        <textarea ng-model = "log"></textarea>
        <ul>
            <li ng-repeat="item in list track by $index">
                <input ng-model="item"> Value: <span ng-bind="item"></span>
            </li>
        </ul>
    </section>
    <script>
        angular.module("myApp", [])
            .controller("TestController", function($scope){
                $scope.log = '';
                $scope.list = $scope.list = [1];

                $scope.pushToList = function() {
                    $scope.list.push(Math.random());
                }

                $scope.changeFirstElement = function() {
                    $scope.list[0] = Math.random();
                }

                $scope.$watchCollection(
                    'list',
                    function(currentValue, oldValue) {
                    $scope.log += [
                        'Current value:',
                        currentValue.toString(),
                        'Old value:',
                        oldValue ? oldValue.toString() : '',
                        '-----',
                        '',
                    ].join('\n')
        }
     )
        });
    </script>
</body>
</html>
当我通过调用$scope.list[0] = Math.random();进行更改时,$ watchCollection会“看到”,但是当我使用输入字段时,$ watchCollection会忽略或“看不到”。为什么是这样?我还能做什么呢?

而且我知道我可以使用深度$ watch,但我很乐意如何通过$ watchCollection实现这一目标。另外,如果我理解正确,性能会更好(参见this question)。

编辑:

这是plunkr

当您单击“将数字添加到列表”时,$ watchCollection将看到更改,并且数组的当前内容将写入textarea。当您通过单击“更改第一个元素”更改第一个数字时,$ watchCollection确实看到已发生更改并再次将数组上的当前内容写入textarea。当您使用输入字段更改值时,使用ng-repeat将数组项作为ng-model。我希望如果我在输入字段中更改一个值,它会触发与单击“更改第一个元素”时相同的行为但是:我希望$ watchCollection应该看到有一个更改,我注册的函数应该写数组的内容到textarea。但这不会发生。

1 个答案:

答案 0 :(得分:1)

问题不在$ watchCollection中。 ng-repeat为每个子项创建范围,因此当您在输入中键入时,仅在ng-repeat子范围中更改项属性,因为item是原始的。如果您有$ scope.list = [{value:1}],则可以更改子作用域中父作用域更改值的值,因为列表[0]和项目共享引用在同一对象上。但是watchCollection仍然不会被触发,因为它只检测到浅层变化。