什么被添加到$ scope。默认情况下,观察者在Angular中?什么触发$摘要?

时间:2014-11-30 17:52:32

标签: angularjs data-binding angularjs-scope

我正在阅读Build Your Own AngularJS并对$scopes$watch$digest的工作原理有一个很好的理解。我了解当您添加自己的$watches并调用自己的$digests时它是如何工作的。但是,我对确切发生的事情感到困惑默认

  1. 默认情况下会将哪些内容添加到$scope.$$watchers?你放在$scope身上的一切?您为ng-model指定的所有内容?都?还有别的吗?

  2. 默认情况下,$digests确实被触发?输入字段更改?输入ng-models的字段?其他

2 个答案:

答案 0 :(得分:9)

在内部使用$watch / $watchCollection / $watchGroup的一些常用指令:

  1. NG-模型
  2. ng-bind / {{}}
  3. ng-show&纳克隐藏
  4. 纳克级
  5. 纳克重复
  6. NG-如果
  7. ng-switch
  8. NG-包括
  9. 请注意,唯一设置双向绑定的是ng-model(范围 - >视图和视图 - >范围)。

    其他人设置了单向绑定(范围 - >视图)。

    简单地暴露某些内容,例如控制器的$scope添加观察者。

    例如,以下内容不会导致添加观察程序:

    angular.module('myApp', []).controller('Controller', function MyCtrl($scope) {
      $scope.value = 1;
    });
    

    与:

    一起
    <body ng-app="myApp" ng-controller="Controller">
    </body>
    

    但是如果用以下内容替换HTML,将添加一个观察者:

    <body ng-app="myApp" ng-controller="Controller">
      <div>{{value}}</div>
    </body>
    

    触发摘要周期时的一些常见情况:

    1. 评估ng-click
    2. ng-model更改时(例如输入输入时)
    3. 通过$http服务
    4. $timeout$interval

    5. 请注意,$apply$digest之间存在很大差异:

      调用scope.$digest()将仅在该范围及其子级上执行观察者。

      调用scope.$apply()将触发$digest上的$rootScope,这意味着将遍历所有范围并执行所有观察者。

      $apply也接受表达式作为参数。此表达式将在try-catch语句中进行评估,任何异常都将传递给$exceptionHandler服务。

      $digest不接受任何论据。

      通常,当您追逐微优化并真正了解自己在做什么时,您只需拨打$digest而不是$apply

答案 1 :(得分:0)

我的理解是,任何双向绑定都会在其范围内获得$watch,但是,如果它是由角内部添加的,那么你就不会得到那个钩子,因为例如,ngModelController具有回调功能,因此您无法使用该回调,我认为范围内的内容不会获得监视,除非它被绑定到视图。

我在源代码中找到的模型绑定上没有使用

$digest - 但我发现$apply有很多用途。事实上,我发现角度代码中$digest的使用很少。我没有查看每个文件,但我确实发现它在表达式解析器here中使用。我觉得这很有意思,但要回答你的问题,$digest经常不会被调用,$apply只会在几次模型绑定中被调用,最明显的是在$commitViewValue() ngModelController 1}}。当输入被触及&#34;(ng-touched)时,它也会调用apply。我还发现$evalAsync也会调用$digest

我在申请/摘要中找到了什么:

//apply method in rootScope
$apply: function(expr) {
    try {
      beginPhase('$apply');
      return this.$eval(expr);
    } catch (e) {
      $exceptionHandler(e);
    } finally {
      clearPhase();
      try {
        $rootScope.$digest();
      } catch (e) {
        $exceptionHandler(e);
        throw e;
      }
    }
  }

正如你所看到的,apply只是一个安全的回绕$digest,所以有人可能会争论使用$ apply而不是摘要。根据源$ digest做了一些疯狂的while循环$scope遍历。

<强> TLDR;

角色小组关于摘要的说明:

  

处理所有{@link ng。$ rootScope.Scope#$ watch watchers}   目前的范围和   它的孩子。因为{@link ng。$ rootScope.Scope#$ watch watcher}的监听器可以改变   模型,$digest()一直在调用{@link ng。$ rootScope.Scope#$ watch watchers}   直到没有更多的听众开枪。这意味着有可能进入无限   环。如果数量为,则此函数将抛出'Maximum iteration limit exceeded.'   迭代次数超过10次。

     

通常,您不能直接拨打$digest()   {@link ng.directive:ngController controllers}或者   {@link ng。$ compileProvider#directive directives}。   相反,你应该调用{@link ng。$ rootScope.Scope#$ apply $ apply()}(通常来自内部   一个{@link ng。$ compileProvider#directive指令}),它将强制$digest()

     

如果您希望在调用$digest()时收到通知,   您可以注册watchExpression功能   {@link ng。$ rootScope.Scope#$ watch $ watch()}没有listener