我正在阅读Build Your Own AngularJS并对$scopes
,$watch
和$digest
的工作原理有一个很好的理解。我了解当您添加自己的$watches
并调用自己的$digests
时它是如何工作的。但是,我对确切发生的事情感到困惑默认。
默认情况下会将哪些内容添加到$scope.$$watchers
?你放在$scope
身上的一切?您为ng-model
指定的所有内容?都?还有别的吗?
默认情况下,$digests
确实被触发?输入字段更改?输入ng-models
的字段?其他
答案 0 :(得分:9)
在内部使用$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()
将触发$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
。