AngularJS权威指南-digest循环

《AngularJS 权威教程》读书笔记,第二十三章——digest 循环和$apply。

序言

浏览器自身有事件监听机制,而 AngularJS 的原理是:启用一个 AngularJS 上下文,这个上下文是运行在 AngularJS 事件循环(即 $digest 循环)内的特定代码。
$digest 循环有两个主要组成部分:

  • $watch 列表
  • $evalAsync 列表

AnuglarJS 双向绑定就是通过给 $watch 列表添加一个又一个的监控函数实现的
$scope 对象上的属性只会在被用于视图时进行双向绑定,也就是只有在用于视图时才会给 $watch 列表添加一个函数
$watch 列表会在 $digest 循环中通过一个叫做“脏值检查”的程序解析

脏值检查

AngularJS 应用持续跟踪当前监控的值:AngularJS 会遍历 $watch 列表,如果从旧值更新后的值没有发生变化,它会继续遍历监控列表;如果值发生了变化,该应用会启用新值并继续遍历 $watch 列表。
AngularJS 遍历完整个 $watch 列表,只要有任何值发生了变化,应用会退回到 $watch 循环中(以防一个值的变化引起另外一个值的变化,所以要再次退回),知道检测到不再有任何变化。
如果这个循环运行 10 次或者更多次,AngularJS 应用会抛出一个异常,同时停止运行,以防应用进入无限循环。

$watch列表

$scope 对象上的 $watch 方法会给 Angular 事件循环内的每个 $digest 调用装配一个脏值检查。如果在表达式上检测到变化,AngularJS 总是会返回 $digest 循环。$watch 方法签名:

1
var unregisterWatch = $scope.$watch(watchExpression, callback[, objectEquality]);

  • 第一个参数:watchExpression,是一个要监控的值或者一个返回应该被监控值的函数
  • 第二个参数:callback(newValue, oldValue, scope),回调监听函数
  • 第三个参数:objectEquality,可选,一个布尔值,用来告诉 AngularJS 是否检查严格相等
  • 返回值:unregisterWatch,unregisterWatch() 将会注销对该值的监听

$watch 方法会在应用初始化时运行一次,此时:newValue === oldValue === undefined

$watchCollection

$watchCollection 是 $watch 用来监控对象或数组弱变化(即对象或数组只是改变了某个属性或者元素)的版本,其他方面两者完全一致。

$evalAsync列表

$evalAsync() 方法是一种在当前作用域上调度表达式在未来某个时刻运行的方式。
$digest 循环运行的第二个操作是执行 $$asyncQueue,可以使用 $evalAsync() 方法访问这个工作队列。
下面的没看懂,不写了。。。

$apply

$apply() 函数的作用:

  1. 可以从 AngularJS 框架的外部让表达式在 AngularJS 上下文内部执行(对于第三方框架很有用)
  2. $apply() 方法会直接调用 $digest() 循环

$apply() 函数接受一个可选的参数:expression(字符串或函数):

  • 如果是字符串,会先在这个字符串上调用 $eval(),以强制 AngularJS 在局部作用域上下文中使用 $eval() 运行字符串表达式;
  • 如果是函数,这个函数将会在所传入的函数作用域上执行;
  • 如果没有参数,就是想要强制运行 $digest 循环