资源说明:引子
这篇文章是写给AngularJS新手的,如果你已经对AngularJS的双向数据绑定有了深入的了解,直接去阅读源代码好了。
背景
AngularJS开发者都想知道双向数据绑定是怎么实现的。与data-binding相关的术语琳琅满目: $watch,$apply,$digest,dirty-checking等等它们是如何工作的呢?让我们从头开始讲起吧
AngularJS 的双向数据绑定是被浏览器逼的
浏览器看上去很美,其实在数据交互这块儿,由于浏览器的“不作为”,导致浏览器的数据刷新成为一个难题。具体来说,浏览器可以很容易地监听一个事件,比如:用户点击一个按钮,或者在输入框里输入东西,为
AngularJS的双向数据绑定是其核心特性之一,它使得模型(Model)与视图(View)之间的数据同步变得简单易行。在AngularJS中,这一机制主要依赖于`$watch`、`$apply`和`$digest`这三个关键概念。
`$watch`是AngularJS中的一个服务,用于监听模型的改变。当你在控制器中创建一个`$watch`,它会将一个表达式添加到`$watch list`(观察者列表)中,这个列表会跟踪所有需要监控的模型变化。每当模型发生变化时,`$watch`就会执行相应的回调函数,更新视图。例如,在HTML中使用`ng-model`指令创建的双向绑定,实际上会在背后创建一个`$watch`来监听该模型的变化。
接着,我们来看`$apply`。当我们在AngularJS的外部(比如在浏览器的事件回调函数中)修改模型时,这些改变不会自动触发视图的更新。这时就需要调用`$apply`方法来将这些改变“告知”AngularJS,让它进行脏检查并执行必要的更新。`$apply`会在当前作用域及其所有父作用域中运行`$digest`循环。
然后,`$digest`是整个过程的核心。它是一个不断迭代的过程,用于检测模型是否有变化。`$digest`遍历`$watch list`,对每个`$watch`执行其表达式,比较新旧值以判断模型是否发生改变。如果发现变化,`$digest`会再次运行,直到没有更多的`$watch`更新,或者达到预设的最大迭代次数(默认为10次)以防止无限循环。一旦`$digest`循环结束,所有必要的DOM更新都会被执行,使视图保持与模型同步。
在实际应用中,AngularJS的模板加载分为编译(compile)和链接(linking)两个阶段。在链接阶段,AngularJS解释器解析模板中的指令,并为每个指令生成对应的`$watch`。例如,`ng-repeat`指令不仅会生成一个迭代器`$watch`,还会为循环中的每个属性(如`person.name`和`person.age`)创建额外的`$watch`。
AngularJS的双向数据绑定原理通过`$watch`监听模型变化,`$apply`确保外部改变能够影响模型,并通过`$digest`循环来检测和处理这些变化,从而实现视图与模型的实时同步。这一机制巧妙地解决了浏览器本身在数据交互和更新上的不足,使得开发者能更专注于业务逻辑,而不是数据同步的问题。
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。
English
