在angular中,提供了ng-model的数据双向绑定指令,当数据发生改变的时候,去更新视图层上的数据,当视图层上的数据发生改变的时候,也会同步的去更新数据,那么angular底层是如何去实现这个功能的呢?
实际上,当我们在页面上写了一个{{xxx}}这样的插值语法的时候,angular会在内部在“$scope”上去设置一个watcher,用来在数据发生改变的时候去更新view。
如图代码,我们传入到“$watch()”的第一个参数是我们需要去监视的源数据的名称,第二个参数是一个回调函数,该函数会在“one”的值发生改变的时候被调用去更新view。
但是,问题是,angular内部是如何知道这个“one”发生了变化的,这时$digest就发生了作用。
在$digest循环中,watcher会被触发,这个时候angularJS会去检测scope模型,如果发生了变化,那么关联到这个watcher的回调函数就会被调用,那么,$digest循环是在什么时候开始的?
实际在调用了$scope.$digest()后,$digest循环就开始了,如果你在ng-click指令中更改了数据,此时angularJS会自动的通过调用$digest()来触发一轮$digest循环,当循环开始后,它会触发每个watcher检查本次的值和上次的值是否相同,如果不相同,则对应的回调函数会被执行。
但是需要注意的是,在上面的例子中,angularJS并不直接调用$digest(),而是调用$scope.$apply(),后者才回去调用$digest。
那么,我们应该什么时候去手动的调用$scope.apply()呢?
如上代码,我们开启一个定时器在两秒改变页面上绑定的一个值,这时view的表现形式是:
我们发现在js的内部数值是发生了变化,但是我们的view界面上数值却没有发生任何改变,这时我们将代码进行更改:
页面上的表现形式如下:
这里我们手动调用了$scope.$apply(),这个时候就手动的告诉了angular的内部我们对这个数据进行了更改,那么他随后就去调用了$scope.$digest()去启动这个循环,使用watcher去检测我们的数据,然后去更新view。
那么$digest会循环多少次呢?
当一个$digest循环运行时,watchers会被执行来检查scope中的models是否发生了变化。如果发生了变化,那么相应的listener函数就会被执行。这涉及到一个重要的问题。如果listener函数本身会修改一个scope model呢?AngularJS会怎么处理这种情况?
答案是$digest循环不会只运行一次。在当前的一次循环结束后,它会再执行一次循环用来检查是否有models发生了变化。这就是脏检查(Dirty Checking),它用来处理在listener函数被执行时可能引起的model变化。因此,$digest循环会持续运行直到model不再发生变化,或者$digest循环的次数达到了10次。因此,尽可能地不要在listener函数中修改model。
注意:$digest循环最少也会运行两次,即使在listener函数中并没有改变任何model。正如上面讨论的那样,它会多运行一次来确保models没有变化。
这篇博客是结合自己在实际开发中遇到的问题,在网上找到的一些其他作者的文章,然后结合自己的一些看法综合写出来的,如有侵权,联系本人马上删除。
参考文档:http://blog.csdn.net/dm_vincent/article/details/38705099
转载于:https://my.oschina.net/u/2941129/blog/868995