理解angularJS的双向绑定

双向绑定是angularJS最核心的一个特性,本文将介绍什么是双向绑定机制以及这个机制是怎么实现的。

一.什么是双向绑定

 要搞清楚什么是双向绑定,首先得知道什么是单向绑定。在angularJS中,单向绑定实际就是用来数据展示的,也就是我们常用的{{value}}和ng-bind。在数据展示的时候,我推荐使用后者,因为后者是在angular渲染完毕后才将数据显示。那么什么是双向绑定呢?单向绑定是$scope到view,那么双向绑定肯定多了一个view到$scope这个方向,即是说页面中的数据发生变化,与之绑定的¥$scope的值也会变化,自然其他用到这个值的地方也会发生变化。

二.双向绑定是如何实现的?

首先,当你在html页面下写下{{aModel}}这个表达式的时候,AngularJS在幕后会为你在scope模型上设置一个watcher,它用来在数据发生变化的时候更新view。这里的watcher和你会在AngularJS中设置的watcher是一样的:

理解angularJS的双向绑定

传入到$watch()中的第二个参数是一个回调函数,该函数在aModel的值发生变化的时候会被调用。当aModel发生变化的时候,这个回调函数会被调用来更新view这一点不难理解,但是,还存在一个很重要的问题!AngularJS是如何知道什么时候要调用这个回调函数呢?换句话说,AngularJS是如何知晓aModel发生了变化,才调用了对应的回调函数呢?难道说会有一个函数每隔一定周期去检查一次?好吧,这个时候就是$digest()出场了。

在$digest循环中,watchers会被触发。当一个watcher被触发时,AngularJS会检测scope模型,如果它发生了变化那么关联到该watcher的回调函数就会被调用。那么,下一个问题就是$digest循环是在什么时候以什么方式开始的?

理解angularJS的双向绑定

但是,到了这里,还有一个小问题。就是angular并不直接调用$digest(),而是调用$scope.$apply(),后者会调用$rootScope.$digest()。因此,一轮$digest循环在$rootScope开始,随后会访问到所有的children scope中的watchers。