为什么Scope。$ apply()调用$ rootScope。$ digest()而不是this。$ digest()?

时间:2012-09-08 18:34:23

标签: angularjs

在AngularJS范围内。$ apply()在每个事件处理程序上调用(输入指令的keydown /输入事件,select指令的更改事件等)和其他一些情况。

small example。似乎在每个keydown上都重新计算并重新绘制了ngRepeat,尽管在另一个范围内发生了更改。

了解这种决定的理由会很有趣。

1 个答案:

答案 0 :(得分:17)

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中包含了一个对象,用于说明观察者评估确实需要从最顶端开始。