一尘不染

AngularJS 中的数据绑定是如何工作的?

javascript

AngularJS 中的数据绑定是如何工作的?


阅读 140

收藏
2022-02-12

共1个答案

一尘不染

AngularJS 会记住该值并将其与之前的值进行比较。这是基本的脏检查。如果值发生变化,则触发 change 事件。

当您从非 AngularJS 世界过渡到 AngularJS 世界时,该$apply()方法调用$digest(). 摘要只是简单的旧脏检查。它适用于所有浏览器并且完全可以预测。

对比脏检查(AngularJS)和更改监听器(KnockoutJSBackbone.js):虽然脏检查看起来很简单,甚至效率低下(我稍后会解决这个问题),但事实证明它在语义上一直是正确的,而更改侦听器有很多奇怪的极端情况,需要依赖跟踪之类的东西来使其在语义上更正确。KnockoutJS 依赖跟踪是 AngularJS 所没有的一个聪明的功能。

更改侦听器的问题:

  • 语法很糟糕,因为浏览器本身不支持它。是的,有代理,但它们在所有情况下都不是语义正确的,当然旧浏览器上没有代理。底线是脏检查允许您执行POJO,而 KnockoutJS 和 Backbone.js 强制您从它们的类继承,并通过访问器访问您的数据。
  • 改变合并。假设您有一个项目数组。假设您想将项目添加到数组中,当您循环添加时,每次添加时都会触发更改事件,这会呈现 UI。这对性能非常不利。你想要的是在最后只更新一次 UI。更改事件的粒度太细了。
  • 更改侦听器立即在 setter 上触发,这是一个问题,因为更改侦听器可以进一步更改数据,从而触发更多更改事件。这很糟糕,因为在您的堆栈中,您可能会同时发生多个更改事件。假设您有两个数组,无论出于何种原因都需要保持同步。您只能添加到其中一个,但每次添加时都会触发一个更改事件,该事件现在对世界的看法不一致。这是一个与线程锁定非常相似的问题,JavaScript 避免了这种问题,因为每个回调都以独占方式执行并完成。更改事件打破了这一点,因为 setter 可能会产生深远的后果,这些后果不是有意的和不明显的,这会再次造成线程问题。事实证明,您要做的是延迟侦听器的执行,并保证,

性能呢?

所以看起来我们很慢,因为脏检查效率低下。这是我们需要查看实数的地方,而不仅仅是理论上的论据,但首先让我们定义一些约束。

人类是:

  • - 任何快于 50 毫秒的速度对于人类来说是无法察觉的,因此可以被视为“即时”。
  • 有限——你不能在一个页面上向一个人显示超过 2000 条信息。除此之外的任何东西都是非常糟糕的用户界面,人类无论如何也无法处理它。

所以真正的问题是:你可以在 50 毫秒内在浏览器上进行多少次比较?这是一个很难回答的问题,因为有许多因素在起作用,但这里有一个测试用例:http: //jsperf.com/angularjs-digest/6,它创建了 10,000 个观察者。在现代浏览器上,这需要不到 6 毫秒。在Internet Explorer 8上大约需要 40 毫秒。如您所见,即使在如今速度较慢的浏览器上,这也不是问题。有一个警告:比较需要简单以适应时间限制......不幸的是,将慢速比较添加到 AngularJS 中太容易了,因此当您不知道自己在做什么时,很容易构建慢速应用程序是做。但是我们希望通过提供一个检测模块来得到答案,它会告诉你哪些是慢速比较。

事实证明,视频游戏和 GPU 使用脏检查方法,特别是因为它是一致的。只要他们超过显示器刷新率(通常为 50-60 Hz,或每 16.6-20 ms),任何超过此的性能都是浪费,所以你最好画更多的东西,而不是提高 FPS。

2022-02-12