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