脏检查机制。
双向数据绑定是 AngularJS 的核心机制之一。当 view 中有任何数据变化时,会更新到 model ,当 model 中数据有变化时,view 也会同步更新,显然,这需要一个监控。
原理就是,Angular 在 scope 模型上设置了一个 监听队列,用来监听数据变化并更新 view 。每次绑定一个东西到 view 上时 AngularJS 就会往 $watch
队列里插入一条 $watch
,用来检测它监视的 model 里是否有变化的东西。当浏览器接收到可以被 angular context 处理的事件时,$digest
循环就会触发,遍历所有的 $watch
,最后更新 dom。
举个栗子
<button ng-click="val=val+1">increase 1</button>
click 时会产生一次更新的操作(至少触发两次 $digest
循环)
按下按钮
浏览器接收到一个事件,进入到 angular context
$digest
循环开始执行,查询每个 $watch
是否变化
由于监视 $scope
.val 的 $watch
报告了变化,因此强制再执行一次 $digest
循环
新的 $digest
循环未检测到变化
浏览器拿回控制器,更新 $scope
.val 新值对应的 dom
$digest
循环的上限是 10 次(超过 10次后抛出一个异常,防止无限循环)。
这个问题换一种说法就是,如何在平级界面模块间进行通信。有两种方法,一种是共用服务,一种是基于事件。
在 Angular 中,通过 factory 可以生成一个单例对象,在需要通信的模块 a 和 b 中注入这个对象即可。
这个又分两种方式
第一种是借助父 controller。在子 controller 中向父 controller 触发($emit
)一个事件,然后在父 controller 中监听($on
)事件,再广播($broadcast
)给子 controller ,这样通过事件携带的参数,实现了数据经过父 controller,在同级 controller 之间传播。
第二种是借助 $rootScope
。每个 Angular 应用默认有一个根作用域 $rootScope
, 根作用域位于最顶层,从它往下挂着各级作用域。所以,如果子控制器直接使用 $rootScope
广播和接收事件,那么就可实现同级之间的通信。