什么是AngularJs中的digest周期
在开始之前,我们需要了解一些与Digest循环相关的术语。它们是AngularJs的watch、watch counts和watch list。
* AngularJs watch。它是由AngularJs框架提供的,用于跟踪范围变量和它们的值的变化。监视器是由AngularJs框架自动创建的。它通常是为数据绑定和AngularJs框架决定的变量而做的。为观察创建的自定义函数被称为观察监听器。
- 观察次数。如果watch计数低于2000,性能会更好。我们可以使用Angular的watchers扩展来计算它们。Angular对数据绑定的变量进行观察,但如果我们愿意,也可以使用watch函数对普通变量进行观察。它的参数是我们明确想要监视的变量。
- 监视列表。维护一个与angular应用程序相关的所有观察列表,即所有被监控的数据绑定。所有的作用域,包括根,都有一个观察列表。
Digest cycle
手表不断地更新新的值,并更新DOM,从而呈现出变化。这个过程负责遍历整个手表的变化。它对手表列表中的手表进行脏检查。脏检查是为了检查变量的当前值和它们之前的值。
- 每当摘要过程发现变量有任何修改,观察监听器就会自动执行。它将变化记录下来,然后通知AngularJs框架来更新DOM。因此,在每个摘要过程结束时,DOM会被更新。
- Angular Context是AngularJs框架的一个运行环境。
- 第一个摘要程序对手表进行脏检查,并检查是否有任何修改。
它再次对前一个周期进行第二周期的脏检查,观察听众。因为可能有一些变量已经被别人改变了。最少进行2次迭代,最多可运行10次。尽管为了更好的性能,最好尽量减少摘要周期。在最大限度后会抛出错误。
第一层和第二层更新。
- 第一层更新。假设变量b被任何事件更新了,那么在第一个循环中,Digest循环会通知AngularJs框架这些变化,之后再进行第二个循环。由于没有更多的更新,它因此更新DOM并完成它。
-
第二层次的手表更新。每当任何一个特定的表(如c)在第一个周期中遇到变化时,摘要进程就会为它执行表监听器。现在观察监听器进一步修改变量a为新的值。在第一个周期后,c被更新。在第二个周期中,我们遇到了a的变化,因此对a进行了更新。现在发生了第三个周期,没有再遇到修改。DOM被更新。
第二级更新的一个例子。
$scope.a = 1;
$scope.b = 2;
$scope.c = 3;
$scope.$watch('a', function( newValue, oldValue ) {
if( newValue != oldValue ) {
console.log("a is modified to " +newValue );
}
});
$scope.$watch('b', function( newValue, oldValue ) {
if( newValue != oldValue ) {
console.log("b is modified to " +newValue );
}
});
$scope.$watch('c', function( newValue, oldValue ) {
if( newValue != oldValue ) {
console.log("c is modified to " +newValue );
if( $scope.c > 50 ) {
$scope.a = 1000;
}
}
});
$rootscope.$watch( function() {
console.log(" digest iteration started ");
});
考虑到范围变量a、b、c是数据绑定的,有资格进入摘要过程。如果我们在浏览器中检查angular应用程序并打开控制台。我们可以跟踪这些变化,因为打印语句会帮助我们。假设c有一个双向绑定的输入框,我们可以很容易地跟踪它被修改的次数。事实上,我们也可以通过对rootscope应用watch函数来检查摘要过程。
$watch:这个函数需要三个参数–watch表达式、监听器和对象平等。除了表达式外,其他两个是可选的。
- Digest过程从根作用域开始,然后再识别其他作用域。如果我们的代码使用DOM事件(ng-click)、带有回调的ajax、带有回调的定时器、浏览器位置的改变、像$apply这样的手动调用,那么它必然会有针对所有这些的摘要过程。
- 我们知道,浏览器负责渲染DOM,它可能有像Timer、On-click等事件。浏览器为这些事件维护一个队列,称为事件队列。它将这些事件发送给Javascript。因此,对这些事件进行摘要处理。如果事件与Javascript无关,即用Jquery或其他语言编写,那么我们有责任编写$apply函数来维护它们的摘要。
$scope.$apply(function() {
});
digest周期的完整方案: