这是Angular的行为我不知道。
假设我在控制器中有一系列项目,并在视图中重复它们。我在视图中有一个按钮,当我点击它时,一个项目被推入数组中。 ng重复列表在视图中更新。到目前为止一切都很好。
但是 如果我只是在控制器内的数组中推送一个新项(比方说,我设置了一个超时),视图中的ng-repeat将不会注册数组的更改。
关于plunker的例子:http://plnkr.co/edit/1mlOpGVOXmnCAa8W5KEx?p=preview
HTML:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.0-beta.4/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<main ng-controller="MainController as ctrl">
<button ng-click="ctrl.addName()">Add an item</button>
<ul>
<li ng-repeat="name in ctrl.names">
{{name.name}}
</li>
</ul>
</main>
</body>
</html>
JS:
angular.module('myApp', [])
.controller('MainController', function(){
var self = this;
self.test = 2;
self.names = [{name: 'example'}];
self.addName = function(){
self.names.push({name: 'new example'});
console.log(self.names)
};
setTimeout(function(){
self.names.push({name: 'another example'});
console.log(self.names);
}, 1000);
});
观察到的行为:单击该按钮将触发addName
功能并将项目添加到列表中。但是setTimeout
会推送数组中的项目,但这不会反映在视图中。在检查控制台日志的结果时,我看到显示的项目具有$$hashKey
属性,并且对数组的简单推送将导致缺少此属性的项目。
问题:在控制器中向项目添加项目的正确方法是什么?我应该使用$ digest还是$ apply或者什么?
答案 0 :(得分:3)
如果任何观察的模型值发生变化,Angular会定期执行脏检查。它在所谓的$digest
周期中这样做。当Angular认为有必要时会自动运行这些循环,但如果事件发生在Angular上下文之外,Angular将不会知道它,不会触发$digest
周期,也不会检测到更改和视图不会更新。
当您将值推送到数组(在Angular上下文之外)时,您需要手动运行$ digest循环,例如通过将函数包装到$scope.evalAsync()
中,这将触发范围内的脏检查。
更新:是的,你也可以拨打$scope.$digest()
,但问题是如果$ digest周期已经开始运行,你将会得到那个不可思议的“$ digest ()已在进行中“错误。
$scope.evalAsync()
不会遇到这个问题,因为它会异步触发$digest
个循环。更重要的是,如果$digest
周期已在进行中,它将尝试在同一周期内完成工作,并且不会不必要地启动新工作。
Ben Nadel也可以看到这个excellent blog post,更详细地解释所有内容(例如,使用$timeout
服务进行比较,这是另一种选择)。