为什么angularjs $ scope。$ digest()更新父范围?

时间:2015-07-22 20:50:07

标签: javascript angularjs

我使用$scope.$digest()方法感到很困惑。据我所知,当我们调用$scope.$digest()时,它不会更新父范围值,所以

  

它处理当前范围的所有观察者及其   儿童

,但是当我调用$scope.$digest()时,它也会更新父范围,在这种情况下是$rootScope

在下面的例子中,我有一个演示。在$rootScope我有一个名为value_on_root的变量,所以每当我在输入上调用onchange事件时,我调用一个角度函数,在其中我改变变量的值{{1 } file_src上的$scope也改变value_on_root上的变量$rootScope的值,所以当我调用$scope.$digest时,更新会调用观察者$rootScope也是。

查看此处的示例

Click to see example in CODEPEN

2 个答案:

答案 0 :(得分:2)

Per This Article

" $ digest循环由于调用$ scope而开始。$ digest()。假设您通过ng-click指令更改处理函数中的范围模型。在这种情况下,AngularJS通过调用$ digest()自动触发$ digest循环。当$ digest周期开始时,它会触发每个观察者。这些观察者检查范围模型的当前值是否与上次计算的值不同。如果是,则执行相应的侦听器函数。因此,如果您在视图中有任何表达式,它们将被更新。除了ng-click之外,还有其他一些内置指令/服务可以让你更改模型(例如ng-model,$ timeout等)并自动触发$ digest循环。

到目前为止,真好!但是,有一个小问题。在上面的例子中, Angular不会直接调用$ digest()。相反,它调用$ scope。$ apply(),后者又调用$ rootScope。$ digest()。因此,摘要周期从$ rootScope开始,随后访问所有调用观察者的子范围。"

然后更新rootscope变量,您会看到代码集中的更改。

答案 1 :(得分:0)

混淆源于您对$scope.$digest下面的解释:

  

据我所知,当我们调用$ scope。$ digest()时,它不会更新父范围值

如果向该范围对象添加或修改属性,则父范围的值 将始终更新。任何JS对象都是如此(除非该对象被冻结或无法接收更新/新属性,但在这种情况下这一点并不重要)。

现在,该范围对象的新属性或修改属性是否反映在DOM中是另一回事。

在您的示例codepen中,您将通过在控制器中为其赋予新值来更新根范围:

$rootScope.value_on_root = "Value updated";

此更新反映在DOM中的原因是由于两件事:

  1. 您已在HTML中的控制器范围对象中隐式注册了value_on_root的观察程序:

    <div><strong>{{value_on_root}}</strong></div>
    
  2. 您的控制器范围正在使用原型继承,因此可以通过控制器的范围访问属性value_on_rootUnderstanding Scopes是一篇很好的文章,解释了AngularJS中的范围继承。来自文章:

      

    如果我们尝试从子范围访问parentScope上定义的属性,JavaScript将首先查看子范围,而不是找到该属性,然后查看继承的范围,并找到该属性。 (如果它没有在parentScope中找到该属性,它将继续原型链......一直到根范围)。

  3. 在您的示例中,因为您当前范围内有value_on_root观察者(由于上面的第1点),并且因为value_on_root可通过您当前的范围访问(由于上面的第2点) ,$digest完全按照预期行事:

      

    它处理当前范围的所有观察者及其子女

    如果我们在当前范围之外有value_on_root观察者,或者您的控制器的范围有isolate scope,则$rootScope上的属性更新不会反映在DOM。

    我稍微修改了您的codepen in this example以证明我的观点。我通过向周围的HTML添加value_on_root隐式地将{{value_on_root}}观察者放在控制器范围之外。请注意,在此示例中,上传图像时不会更新外部value_on_root

    如果您在my example中将$digest更改为$apply,则外部value_on_root会更新。