Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
342 views
in Technique[技术] by (71.8m points)

javascript - 数据绑定如何在AngularJS中运行?(How does data binding work in AngularJS?)

How does data binding work in the AngularJS framework?

(数据绑定如何在AngularJS框架中工作?)

I haven't found technical details on their site .

(我没有在他们的网站上找到技术细节。)

It's more or less clear how it works when data is propagated from view to model.

(当数据从视图传播到模型时,它或多或少清楚它是如何工作的。)

But how does AngularJS track changes of model properties without setters and getters?

(但是AngularJS如何在没有setter和getter的情况下跟踪模型属性的变化?)

I found that there are JavaScript watchers that may do this work.

(我发现有一些JavaScript观察者可以做这项工作。)

But they are not supported in Internet Explorer 6 and Internet Explorer 7 .

(但Internet Explorer 6Internet Explorer 7不支持它们。)

So how does AngularJS know that I changed for example the following and reflected this change on a view?

(那么AngularJS如何知道我改变了例如以下内容并在视图上反映了这一变化?)

myobject.myproperty="new value";
  ask by Pashec translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

AngularJS remembers the value and compares it to a previous value.

(AngularJS会记住该值并将其与之前的值进行比较。)

This is basic dirty-checking.

(这是基本的脏检查。)

If there is a change in value, then it fires the change event.

(如果值发生变化,则会触发更改事件。)

The $apply() method, which is what you call when you are transitioning from a non-AngularJS world into an AngularJS world, calls $digest() .

($apply()方法是您从非AngularJS世界转换到AngularJS世界时调用的方法,它调用$digest() 。)

A digest is just plain old dirty-checking.

(摘要只是简单的旧脏检查。)

It works on all browsers and is totally predictable.

(它适用于所有浏览器,完全可以预测。)

To contrast dirty-checking (AngularJS) vs change listeners ( KnockoutJS and Backbone.js ): While dirty-checking may seem simple, and even inefficient (I will address that later), it turns out that it is semantically correct all the time, while change listeners have lots of weird corner cases and need things like dependency tracking to make it more semantically correct.

(将脏检查(AngularJS)与更改侦听器( KnockoutJSBackbone.js )进行对比:虽然脏检查看似简单,甚至效率低下(我稍后会解决),但事实证明它在语义上始终是正确的,虽然更改侦听器有很多奇怪的角落情况,并且需要依赖跟踪之类的东西,以使其在语义上更正确。)

KnockoutJS dependency tracking is a clever feature for a problem which AngularJS does not have.

(KnockoutJS依赖关系跟踪是AngularJS没有的问题的一个聪明的功能。)

Issues with change listeners:(更改侦听器的问题:)

  • The syntax is atrocious, since browsers do not support it natively.

    (语法很糟糕,因为浏览器本身不支持它。)

    Yes, there are proxies, but they are not semantically correct in all cases, and of course there are no proxies on old browsers.

    (是的,有代理,但在所有情况下它们在语义上都不正确,当然在旧浏览器上没有代理。)

    The bottom line is that dirty-checking allows you to do POJO , whereas KnockoutJS and Backbone.js force you to inherit from their classes, and access your data through accessors.

    (底线是脏检查允许你做POJO ,而KnockoutJS和Backbone.js强迫你从他们的类继承,并通过访问器访问你的数据。)

  • Change coalescence.

    (改变合并。)

    Suppose you have an array of items.

    (假设您有一系列项目。)

    Say you want to add items into an array, as you are looping to add, each time you add you are firing events on change, which is rendering the UI.

    (假设您要将项目添加到数组中,因为您要循环添加,每次添加时都会触发更改事件,即呈现UI。)

    This is very bad for performance.

    (这对性能非常不利。)

    What you want is to update the UI only once, at the end.

    (你想要的是最后只更新一次UI。)

    The change events are too fine-grained.

    (变更事件过于细粒度。)

  • Change listeners fire immediately on a setter, which is a problem, since the change listener can further change data, which fires more change events.

    (更改侦听器会立即在setter上触发,这是一个问题,因为更改侦听器可以进一步更改数据,从而触发更多更改事件。)

    This is bad since on your stack you may have several change events happening at once.

    (这很糟糕,因为在您的堆栈上,您可能会同时发生多个更改事件。)

    Suppose you have two arrays which need to be kept in sync for whatever reason.

    (假设您有两个阵列需要保持同步,无论出于何种原因。)

    You can only add to one or the other, but each time you add you fire a change event, which now has an inconsistent view of the world.

    (您只能添加到其中一个,但每次添加时都会触发一个更改事件,该事件现在具有不一致的世界视图。)

    This is a very similar problem to thread locking, which JavaScript avoids since each callback executes exclusively and to completion.

    (这是一个非常类似于线程锁定的问题,JavaScript避免了这个问题,因为每个回调都是独占执行完成的。)

    Change events break this since setters can have far-reaching consequences which are not intended and non obvious, which creates the thread problem all over again.

    (更改事件打破了这一点,因为setter可能会产生影响深远的后果,这些后果不是有意的,也不是非常明显的,这会再次产生线程问题。)

    It turns out that what you want to do is to delay the listener execution, and guarantee, that only one listener runs at a time, hence any code is free to change data, and it knows that no other code runs while it is doing so.

    (事实证明,你想要做的是延迟监听器的执行,并保证一次只运行一个监听器,因此任何代码都可以自由地改变数据,并且它知道没有其他代码在运行时运行。)

What about performance?(性能怎么样?)

So it may seem that we are slow, since dirty-checking is inefficient.

(所以看起来我们很慢,因为脏检查是低效的。)

This is where we need to look at real numbers rather than just have theoretical arguments, but first let's define some constraints.

(这是我们需要查看实数而不仅仅是理论参数的地方,但首先让我们定义一些约束。)

Humans are:

(人类是:)

  • Slow — Anything faster than 50 ms is imperceptible to humans and thus can be considered as "instant".

    ( - 任何比50毫秒快的东西都是人类察觉不到的,因此可以被视为“瞬间”。)

  • Limited — You can't really show more than about 2000 pieces of information to a human on a single page.

    (有限 - 您无法在一个页面上向人类显示超过2000条信息。)

    Anything more than that is really bad UI, and humans can't process this anyway.

    (除此之外的任何东西都是非常糟糕的UI,人类无论如何都无法处理它。)

So the real question is this: How many comparisons can you do on a browser in 50 ms?

(所以真正的问题是:你可以在50毫秒内对浏览器进行多少次比较?)

This is a hard question to answer as many factors come into play, but here is a test case: http://jsperf.com/angularjs-digest/6 which creates 10,000 watchers.

(这是一个很难回答的问题,因为有很多因素可以发挥作用,但这里有一个测试案例: http//jsperf.com/angularjs-digest/6 ,创造了10,000个观察者。)

On a modern browser this takes just under 6 ms.

(在现代浏览器上,这需要不到6毫秒。)

On Internet Explorer 8 it takes about 40 ms.

(在Internet Explorer 8上大约需要40毫秒。)

As you can see, this is not an issue even on slow browsers these days.

(正如您所看到的,即使在速度较慢的浏览器上,这也不是问题。)

There is a caveat: The comparisons need to be simple to fit into the time limit... Unfortunately it is way too easy to add a slow comparison into AngularJS, so it is easy to build slow applications when you don't know what you are doing.

(有一点需要注意:比较需要很简单才能适应时间限制...不幸的是,在AngularJS中添加慢速比较太容易了,所以当你不知道你是什么时很容易构建慢速应用程序是做。)

But we hope to have an answer by providing an instrumentation module, which would show you which are the slow comparisons.

(但是我们希望通过提供一个仪器模块得到答案,该模块可以向您展示哪些是缓慢的比较。)

It turns out that video games and GPUs use the dirty-checking approach, specifically because it is consistent.

(事实证明,视频游戏和GPU使用脏检查方法,特别是因为它是一致的。)

As long as they get over the monitor refresh rate (typically 50-60 Hz, or every 16.6-20 ms), any performance over that is a waste, so you're better off drawing more stuff, than getting FPS higher.

(只要它们超过显示器刷新率(通常为50-60 Hz,或每16.6-20 ms),任何性能都是浪费,所以你最好不要绘制更多的东西,而不是让FPS更高。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...