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

我还没有在他们的网站上找到技术细节。当数据从视图传播到模型时,它是如何工作的,这或多或少是清楚的。但是AngularJS如何在没有setter和getter的情况下跟踪模型财产的更改?

我发现有JavaScript观察者可能会做这项工作。但Internet Explorer 6和Internet Explorer 7不支持它们。那么AngularJS如何知道我更改了例如以下内容,并将此更改反映在视图上?

myobject.myproperty="new value";

当前回答

AngularJs支持双向数据绑定。意味着您可以访问数据视图->控制器和控制器->视图

例如。

1)

// If $scope have some value in Controller. 
$scope.name = "Peter";

// HTML
<div> {{ name }} </div>

O/P

Peter

您可以在ng模型中绑定数据,如:-2)

<input ng-model="name" />

<div> {{ name }} </div>

在上面的示例中,无论用户将给出什么输入,它都将在<div>标记中可见。

如果要将输入从html绑定到控制器:-3)

<form name="myForm" ng-submit="registration()">
   <label> Name </lbel>
   <input ng-model="name" />
</form>

如果您想在控制器中使用输入名称,

$scope.name = {};

$scope.registration = function() {
   console.log("You will get the name here ", $scope.name);
};

ng模型绑定我们的视图并在表达式{{}}中呈现它。ng模型是在视图中显示给用户并与用户交互的数据。因此,很容易在AngularJs中绑定数据。

其他回答

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

$apply()方法调用$digital(),它是当您从非AngularJS世界转换到AngularJS时调用的方法。摘要只是一个简单的旧检查。它适用于所有浏览器,完全可以预测。

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

更改侦听器的问题:

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

性能如何?

因此,我们似乎很慢,因为脏检查效率很低。这就是我们需要研究实数的地方,而不仅仅是理论论证,但首先我们来定义一些约束条件。

人类是:

慢-任何速度超过50毫秒的东西都是人类无法察觉的,因此可以被视为“瞬间”。有限-你不能在一个页面上向人类显示超过2000条信息。除此之外的任何东西都是非常糟糕的UI,人类无论如何都无法处理它。

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

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

Angular.js为我们在视图中创建的每个模型创建一个观察者。每当一个模型被更改时,一个“ng dirty”类就会被附加到该模型上,因此观察者将观察所有具有“ng dirt”类的模型,并在控制器中更新它们的值,反之亦然。

AngularJS借助三个强大的函数来处理数据绑定机制:$watch()、$digital()和$apply()。大多数时候AngularJS都会调用$scope$watch()和$scope$digest(),但是在某些情况下,您可能需要手动调用这些函数来更新新值。

$watch():-

此函数用于观察$scope上变量的变化。它接受三个参数:表达式、监听器和相等对象,其中监听器和相等对象是可选参数。

$digest()-

此函数迭代$scope对象中的所有手表,及其子$scope对象(如果有)。当$digest()迭代时在手表上,它检查表达式的值是否改变。如果值已更改,AngularJS将使用新值和旧值。调用$digest()函数每当AngularJS认为有必要时。例如,在按钮之后或者在AJAX调用之后。在某些情况下,AngularJS不会为您调用$digest()函数。在这种情况下,你必须你自己说吧。

$apply()-

Angular确实会自动神奇地更新那些在AngularJS上下文中。当您在Angular上下文(如浏览器DOM事件、setTimeout、XHR或第三个party库),则需要通过手动调用$apply()。当$apply()函数调用完成时AngularJS在内部调用$digital(),因此所有数据绑定都是更新。

这是我的基本理解。这很可能是错误的!

通过传递函数(返回要watch)转换为$watch方法。必须在代码块内对关注的项目进行更改由$apply方法包装。在$apply结束时,调用$digest方法通过每一块手表和检查,看看它们是否发生了变化上次运行$digest时。如果发现任何更改,则再次调用摘要,直到所有更改稳定下来。

在正常开发中,HTML告诉AngularJS编译器为您创建手表,并且控制器方法已经在$apply中运行。所以对于应用程序开发人员来说,它是完全透明的。

单向数据绑定是一种从数据模型中获取值并插入到HTML元素中的方法。无法从视图更新模型。它用于经典模板系统。这些系统仅在一个方向上绑定数据。Angular应用程序中的数据绑定是模型和视图组件之间数据的自动同步。

数据绑定允许您将模型视为应用程序中的唯一真实来源。视图始终是模型的投影。如果模型已更改,视图将反映更改,反之亦然。