首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >默认情况下,在$scope.$$watchers中添加了什么(角)?是什么触发了$digests?

默认情况下,在$scope.$$watchers中添加了什么(角)?是什么触发了$digests?
EN

Stack Overflow用户
提问于 2014-11-30 17:52:32
回答 2查看 2.3K关注 0票数 0

我正在阅读构建自己的AngularJS,并对$scopes$watch$digest的工作原理有了很好的理解。我理解当您添加自己的$watches并调用自己的$digests时,它是如何工作的。然而,我对默认情况下究竟发生了什么感到困惑。

  1. 默认情况下,什么被添加到$scope.$$watchers中?你在$scope上放的所有东西?你分配给ng-model的所有东西?两者都有?还有别的吗?
  2. 默认情况下,$digests是什么时候触发的?输入字段更改?用ng-models输入字段?另一个?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-30 19:53:36

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

  1. 吴模型
  2. ng-bind /{}
  3. 五-秀与藏
  4. 五班
  5. ng-重复
  6. 吴-如果
  7. 五开关
  8. ng-包括

请注意,唯一设置双向绑定的是ng-model ( ->视图和视图->作用域)。

其他的则设置单向绑定(作用域->视图)。

简单地公开一些东西,例如控制器的$scope,而不是,就会添加一个观察者。

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

代码语言:javascript
复制
angular.module('myApp', []).controller('Controller', function MyCtrl($scope) {
  $scope.value = 1;
});

连同:

代码语言:javascript
复制
<body ng-app="myApp" ng-controller="Controller">
</body>

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

代码语言:javascript
复制
<body ng-app="myApp" ng-controller="Controller">
  <div>{{value}}</div>
</body>

触发摘要周期时的一些常见场景如下:

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

请注意,$apply$digest之间有一个很大的区别

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

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

$apply还接受一个表达式作为参数。该表达式将在try语句中进行计算,任何异常都将传递给$exceptionHandler服务。

$digest不接受任何参数。

通常,您只在追逐微优化并且真正知道自己在做什么时才调用$digest而不是$apply

票数 9
EN

Stack Overflow用户

发布于 2014-11-30 18:38:19

我的理解是,任何双向绑定都会在其作用域中得到一个$watch,但是,如果它是由角度内嵌添加的,则不会得到这个钩子,因为,例如,ngModelController有回调,所以您不能使用回调,我认为作用域上的内容不会得到手表,除非它绑定到视图上。

根据我在源代码中发现的内容,$digest并不用于模型绑定--但我发现了$apply的许多用途。事实上,我在角码中几乎没有发现$digest的用途。我没有查看每个文件,但我确实发现表达式解析器这里中使用了它。我觉得这很有趣,但为了回答您的问题,$digest在不经常调用,而$apply只在几次使用模型绑定的情况下被调用,最显著的是在ngModelController中的$commitViewValue()上。当输入被“触摸”(ng-touched)时,它也会调用apply。我还发现$evalAsync也调用$digest

我在“申请”/“摘要”上发现的确切情况:

代码语言:javascript
复制
//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;
      }
    }
  }

正如您所看到的,应用实际上只是$digest的一个安全包装,因此人们可能会认为使用$apply而不是文摘。根据源,$digest做了一些疯狂的同时循环$scope遍历。

TLDR;

结束语组的注释:

处理当前作用域及其子范围的所有{@链接ng.$rootScope.Scope#$watch观察者}。因为{@链接ng.$rootScope.Scope#$watch观察者}的侦听器可以更改模型,所以$digest()一直调用{@链接ng.$rootScope.Scope#$watch观察者},直到没有更多侦听器触发为止。这意味着有可能进入无限循环。如果迭代次数超过10,此函数将抛出'Maximum iteration limit exceeded.'。 通常,您不直接在{@link ng.directive:ngController ng.directive:ngController}或{@link ng.$compileProvider#directive指令}中调用ng.$compileProvider#directive。相反,您应该调用{@link ng.$rootScope.Scope#$apply $apply()} (通常在{@link ng.$compileProvider#directive指令}中),这将强制执行$digest()。 如果希望在任何时候调用$digest()时都得到通知,则可以向{@link ng.$rootScope.Scope#$watch $watch()}注册没有listenerwatchExpression函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27216294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档