在 AngularJS 中,scope.$apply() 在每个事件处理程序(输入指令的 keydown/input 事件、选择指令的更改事件等)和其他一些情况下被调用。
见小例子。似乎 ngRepeat 在每次按键时都会重新计算和重新绘制,尽管事实上其他范围内发生了变化。
知道这种决定的理由会很有趣。
有 AngularJS 作者在这方面会很棒,但我相信 $digest() 需要在 $rootScope 上调用,因为在转发器中触发的更改可能会对其他范围(甚至 $rootScope)产生副作用。
问题是在子作用域中触发的方法可以影响父作用域中的对象(因为子作用域继承自父作用域)。因此,即使在子作用域中定义的函数不能修改来自父作用域的对象引用,它们仍然可以修改在父作用域中定义的对象中的值。
上面的内容可能听起来有点神秘,所以让我们考虑一个(有点人为的)带有项目列表的示例:
$scope.items = [{name: 'foo', value:0}, {name: 'bar', value:0}, {name: 'baz', value:0}];
现在,让我们使用 ng-Repeat 来显示上面的列表,假设点击一个项目应该增加其他项目的值(再一次,这个例子有点人为,但这里的重点是在一个范围内触发的动作可以在其他范围内有副作用)。它可以是这样的:
$scope.incOther = function(item) {
for (var i=0; i<$scope.items.length; i++){
if ($scope.items[i] !== item){
$scope.items[i].value++;
}
}
};
示例函数将修改其他范围内的值,AngularJS - 以显示正确的结果 - 需要评估父范围内的观察者(直到 $rootScope 因为我们不知道对象在哪里定义)。
这是说明这一点的完整 jsFiddle:http: //jsfiddle.net/pkozlowski_opensource/Z6e5g/3/
事实上,上面的 jsFiddle 还在 $rootScope 中包含了一个对象,以说明观察者评估确实需要从最顶层开始。