AngularJS $watchCollection 结合 ng-repeat

AngularJS $watchCollection combined with 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 执行 "see",但当我使用输入字段时,更改被忽略,或者 $watchCollection "not seen"。为什么是这样?我还能做什么?

而且我知道我可以改用深度 $watch,但我对如何使用 $watchCollection 实现这一点很感兴趣。也因为如果我理解正确的话性能会更好(参见this question)。

编辑:

这是一个plunkr

当您单击 "Add number to list" 时,$watchCollection 将看到更改并且数组的当前内容被写入文本区域。当您通过单击 "Change first element" 更改第一个数字时,$watchCollection 确实看到发生了更改,并再次将数组中的当前内容写入文本区域。当您使用 ng-repeat 将数组项作为 ng-model 放置在那里的输入字段更改值时。我希望如果我更改输入字段中的值,它会触发与单击 "Change first element" butten 时相同的行为:我希望 $watchCollection 应该看到有变化并且我注册的函数应该写数组的内容到文本区域。但这并没有发生。

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