变化监测
Angular的双向绑定是基于变化监测来实现的,JS内没有提供通知数据变化的机制,因此Angular需要自己去完成这件事。
Angular并不捕捉数据对象的变化,而是在某个适当的时机去检查数据是否发生了变化。要想把控这个时机,首先需要知道是何时合适,也就是数据何时可能发生变化?
数据变化的时机
数据在三种情况下可能变化:
- 用户在页面操作,触发某类事件,click,change...
- 前后端发生交互。
- 延迟或者定时任务处理程序。
这三种情况由共同点,那就是都是异步操作。
已经知道异步操作可能引起数据变化,那么如何在这个时候发起通知?
如何通知
Angular2是对AngularJs进行了重写,AngularJs是对异步操作的情况进行了重写,比如ng-click,ng-change,$timeOut...,使用这些封装后的事件和方法取代原有的,会自动触发$apply(fn)方法,(因为封装后的异步处理运行在Angular环境下。)从而开启$diggest循环,遍历$watch列表,开始变化监测。
Angular2则引入zoneJs,fork了一个NgZone服务,zoneJs简单理解就是一个异步事件拦截器,zone能hook到异步任务的上下文环境,改变异步任务的上下文,为这个异步任务添加一些钩子,从而在异步任务的关键节点利用子函数(默认自带的一些方法)来做一些处理,比如开始、结束、异常时的钩子函数。自带的钩子在复杂情况下可能不够用,因此Zones对所有的异步任务进行了封装,使得这些异步任务可运行于Zone上下文环境下。
发生异步事件后,就会进入zoneJS的环境,触发钩子函数,通知变化检查。
变化检查-脏检查
脏检查对所有的变量的旧值与新值进行比较,不相等就修改对应的视图。