数据绑定在AngularJS
框架中是如何工作的?
我在他们的网站上没有找到技术细节。当数据从视图传播到模型时,或多或少都清楚它是如何工作的。但是AngularJS如何在没有setters和getters的情况下跟踪模型属性的变化?
我发现有一些JavaScript watchers可以完成这项工作。但它们在Internet Explorer 6和Internet Explorer 7中不支持。那么,AngularJS如何知道我改变了例如以下内容,并将这种改变反映在视图上?
myobject.myproperty="new value";
AngularJS会记住这个值并将其与之前的值进行比较。这就是基本的脏检查。如果值有变化,那么它就会触发变化事件。
$apply()
方法,也就是你从非AngularJS世界过渡到AngularJS世界时调用的,调用$digest()
。文摘只是普通的老式脏检查。它在所有的浏览器上都能工作,并且是完全可预测的。
对比一下dirty-checking(AngularJS)和change listeners(KnockoutJS和Backbone.js)。虽然dirty-checking看起来很简单,甚至是低效的(我将在后面讨论这个问题),但事实证明,它在语义上一直是正确的,而change listeners有很多奇怪的角落情况,需要像依赖性跟踪这样的东西来使它在语义上更加正确。KnockoutJS的依赖性跟踪是一个聪明的功能,用于解决AngularJS所没有的问题。
所以看起来我们很慢,因为脏检查的效率很低。这时我们需要看一下真实的数字,而不仅仅是理论上的争论,但首先让我们定义一些约束。
人类是。
*慢 - 任何超过50 ms的速度对人类来说都是无法察觉的,因此可以被认为是 "即时 "的。
有限 - 你不能在一个页面上向人类展示超过2000条的信息。任何超过这个数量的信息都是非常糟糕的用户界面,而且人类无论如何都无法处理这些信息。
因此,真正的问题是这样的。在浏览器上,你能在50 ms内进行多少次比较?这是一个很难回答的问题,因为有很多因素在起作用,但这里有一个测试案例:http://jsperf.com/angularjs-digest/6,它创建了10,000个观察者。在一个现代浏览器上,这只需要不到6 ms。在Internet Explorer 8上,需要大约40 ms。正如你所看到的,即使在现在的慢速浏览器上,这也不是一个问题。有一个注意事项:比较需要简单,以适应时间的限制......不幸的是,在AngularJS中添加一个慢速比较是太容易了,所以当你不知道你在做什么的时候,很容易建立慢速应用。但我们希望通过提供一个工具模块来解决这个问题,它将显示哪些是慢速比较。
事实证明,视频游戏和GPU使用脏器检查的方法,特别是因为它是一致的。只要它们能超过显示器的刷新率(通常是50-60赫兹,或每16.6-20毫秒),任何超过这个频率的性能都是浪费,所以你最好多画一些东西,而不是让FPS更高。
这是我的基本理解。它很可能是错误的!
1.项目是通过传递一个函数(返回要观察的东西)给$watch
方法来观察的。
观察)到$watch
方法。
2.2. 对被监视项目的改变必须在一个代码块中进行
由$apply'方法包装。 3.3. 在"$apply "结束时,"$digest "方法被调用。 在
$apply'结束时,调用`$digest'方法,该方法检查每一个手表,并检查它们是否自
上次"$digest "运行后,它们是否发生了变化。
4.4. 如果发现任何变化,则再次调用digest,直到所有变化稳定下来。
在正常的开发中,HTML中的数据绑定语法告诉AngularJS编译器为你创建手表,控制器方法已经在$apply
中运行。所以对应用程序开发人员来说,这一切都是透明的。
我自己也想过这个问题,有一段时间了。如果没有设置器,AngularJS
如何注意到$scope
对象的变化?它是否对它们进行轮询?
实际上,它是这样做的。你修改模型的任何 "正常 "地方已经从AngularJS
的内部调用了,所以它在你的代码运行后自动为你调用$apply
。假设你的控制器有一个方法与某个元素上的ng-click'挂钩。因为
AngularJS为你连接了该方法的调用,它有机会在适当的地方进行
$apply'。同样,对于直接出现在视图中的表达式,这些表达式会被AngularJS
执行,所以它可以做$apply
。
当文档中提到必须手动调用$apply
来处理AngularJS'以外的代码时,它是指那些在运行时并不来自
AngularJS'本身的调用栈的代码。