我正在阅读构建自己的AngularJS,并对$scopes、$watch和$digest的工作原理有了很好的理解。我理解当您添加自己的$watches并调用自己的$digests时,它是如何工作的。然而,我对默认情况下究竟发生了什么感到困惑。
$scope.$$watchers中?你在$scope上放的所有东西?你分配给ng-model的所有东西?两者都有?还有别的吗?$digests是什么时候触发的?输入字段更改?用ng-models输入字段?另一个?发布于 2014-11-30 19:53:36
在内部使用$watch / $watchCollection / $watchGroup的一些常见指令:
请注意,唯一设置双向绑定的是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>触发摘要周期时的一些常见场景如下:
ng-click被评估时ng-model更改时(例如输入输入时)$http服务提供$timeout和$interval中请注意,$apply和$digest之间有一个很大的区别
调用scope.$digest()将只在该范围及其子程序上执行观察者。
调用scope.$apply()将触发$rootScope上的$digest,这意味着将遍历所有作用域并执行所有观察者。
$apply还接受一个表达式作为参数。该表达式将在try语句中进行计算,任何异常都将传递给$exceptionHandler服务。
$digest不接受任何参数。
通常,您只在追逐微优化并且真正知道自己在做什么时才调用$digest而不是$apply。
发布于 2014-11-30 18:38:19
我的理解是,任何双向绑定都会在其作用域中得到一个$watch,但是,如果它是由角度内嵌添加的,则不会得到这个钩子,因为,例如,ngModelController有回调,所以您不能使用回调,我认为作用域上的内容不会得到手表,除非它绑定到视图上。
根据我在源代码中发现的内容,$digest并不用于模型绑定--但我发现了$apply的许多用途。事实上,我在角码中几乎没有发现$digest的用途。我没有查看每个文件,但我确实发现表达式解析器这里中使用了它。我觉得这很有趣,但为了回答您的问题,$digest在不经常调用,而$apply只在几次使用模型绑定的情况下被调用,最显著的是在ngModelController中的$commitViewValue()上。当输入被“触摸”(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;
}
}
}正如您所看到的,应用实际上只是$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()}注册没有listener的watchExpression函数。
https://stackoverflow.com/questions/27216294
复制相似问题