数据绑定如何在AngularJS中运行?

Pashec 1924 javascript data-binding angularjs

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

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

我发现有一些JavaScript观察者可以做这项工作.但Internet Explorer 6Internet Explorer 7不支持它们.那么AngularJS如何知道我改变了例如以下内容并在视图上反映了这一变化?

myobject.myproperty="new value";

Misko Hevery.. 2735

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

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

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

更改侦听器的问题:

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

性能怎么样?

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

人类是:

  • - 任何比50毫秒快的东西都是人类察觉不到的,因此可以被视为"瞬间".

  • 有限 - 您无法在一个页面上向人类显示超过2000条信息.除此之外的任何东西都是非常糟糕的UI,人类无论如何都无法处理它.

所以真正的问题是:你可以在50毫秒内对浏览器进行多少次比较?这是一个很难回答的问题,因为有很多因素可以发挥作用,但这是一个测试案例:http://jsperf.com/angularjs-digest/6,创造了10,000个观察者.在现代浏览器上,这需要不到6毫秒.在Internet Explorer 8上大约需要40毫秒.正如您所看到的,即使在速度较慢的浏览器上,这也不是问题.有一点需要注意:比较需要很简单才能适应时间限制...不幸的是,在AngularJS中添加慢速比较太容易了,所以当你不知道你是什么时很容易构建慢速应用程序是做.但是我们希望通过提供一个仪器模块得到答案,该模块可以向您展示哪些是缓慢的比较.

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

  • 整个答案很棒,除了"只要它们达到50 fps,任何表现都是浪费,因为人眼无法欣赏它,所以你最好抽出更多的东西,而不是让fps更高." 根据您的应用程序,该声明完全不正确.眼睛肯定可以欣赏超过50 fps,而且随着VR显示的各种问题(阅读John Carmack或Michael Abrash的最新版本,特别是后者的GDC 2013 VR讲话),50 fps实际上太慢了.除此之外,你的答案很棒.我只是不想传播错误的信息. (158认同)
  • 只是想知道,如果您的应用程序像Twitter或评论线程/论坛,并且您实现基于Angular的无限滚动,您可能会遇到"2000条信息""限制".单个注释可以轻松地为作者的名称,配置文件img,内容,日期时间等提供多个变量.另外,假设我们有一个巨大的数组用于存储所有注释/帖子,每次脏检查都需要扫描这个数组,我我对吗?这会使浏览器有时会有点滞后,这是一种糟糕的用户体验.在这种情况下,您建议我们做些什么来确保合理的表现? (67认同)
  • 这句话可以很容易地反过来说:"肮脏的检查是一个聪明的特征,对于一个没有淘汰的问题".ES6正在使用observables和angular正在摆脱脏检查.现实世界追上了这个答案并证明它是错误的. (33认同)
  • @Mark - 是的,在KO中你只需添加.extend({throttle:500})等待最后一次更改事件后500毫秒,然后再对其进行操作. (32认同)
  • "任何超过50毫秒的东西都是人类无法察觉的"并非如此.在测试中,我们发现我们的客户可以轻松区分50ms更新延迟(20fps)和16.6ms更新延迟(60fps).即使人们没有有意识地注册帧速率,以前者速度运行的场景总是变得更差,"感觉如何"评级. (17认同)
  • @DavidRivers us是μs,就像在utorrent1μs= 0.000001s中一样 (10认同)
  • 在手机上,如此多的脏检查可能会造成问题.查看有关手机上Javascript速度的文章."每次更改的更新"不是访问器方法的必然结果,它们可以像Angular摘要周期一样排队.除了他们将确切地知道改变了什么,而不是通过所有绑定.事实上,许多移动浏览器都支持__defineSetter__和__defineGetter__,这可能有助于简化语法,将事物标记为可能很脏. (8认同)
  • 我曾经要求在页面上制作带有2000+元素的应用程序(大表),并使用角度进行制作,结果表明绑定和渲染不是60ms,最新机器上的30-40秒,然后切换到主干和booom 30k +元素,内联编辑,绑定等,~5ms滞后 (8认同)
  • "假设您要将项目添加到数组中,因为您要循环添加,每次添加时都会在更改时触发事件,这会渲染UI.这对性能非常不利"如果您知道自己在做什么Backbone或任何其他框架,您只对数组集事件(集合重置)作出反应,而不是对每个单独的项目作出反应. (7认同)
  • "改变听众立刻解雇" - 他们没有*.我们不能只是将侦听器排队等待当前函数执行完毕后,与Angular相同,除非不需要在最后调查数百或数千个属性? (6认同)
  • 所以我读到了这个答案,并没有解释*AngularJS如何真正起作用而不是模糊的"记住价值并将其与之前的价值进行比较",但是在其他实施方案中,它们已成为一场狂欢.很好..因为问题是*不*关于这样甚至是关于性能. (6认同)
  • 使用许多较小的示波器,你不会获得更高的性能吗? (5认同)
  • @Lucas你做[一次性绑定](https://code.angularjs.org/1.3.10/docs/guide/expression#one-time-binding). (5认同)
  • @JasonGoemaat除非角度需要进入它的循环(这只会在DOM中出现一个愤怒的事件或者愤怒的$ http ajax调用或$ apply调用时发生)然后它不会在背景标签上浪费一点点榨汁来肮脏检查 (3认同)
  • 这应该是有角度的文档.截至目前,Angular文档是我见过的最深奥的文档之一. (3认同)
  • @ misko hevery:"改变监听器立即触发setter",这不是所有情况,你可以改变聚合事件的监听器,并在摘要周期中触发他们的监听器. (3认同)
  • @Misko Hevery:你能举例说明代理在语义上是否正确吗? (2认同)
  • @ user252690通常,DOM事件监听应该通过Angular指令完成.DOM事件监听,jQuery和其他DOM相关代码不属于Angular应用程序中的"用户代码".相反,如果Angular尚未支持您的需求,那么您应该实现一个指令("库代码")以将其从"用户代码"中抽象出来.在某些情况下,您可能会觉得实现新指令的成本超过了好处(干净的代码,关注点的分离,可重用性),在这种情况下,您可以将事件处理包装在`$ scope.$ apply`中. (2认同)
  • @Infeligo你应该检查一下Rx.Js或Bacon.js和功能反应编程(FRP),因为它旨在解决你所描述的确切问题. (2认同)
  • 您是否可以使用脏检查提供有关视频游戏信息的链接?我找不到任何关于它的东西. (2认同)
  • @ norbertas.gaulia这表示你的实现有错,而不是有角度的. (2认同)
  • 50ms不是50fps,它是20fps而且非常慢.对于50fps,$ digest最多需要20ms. (2认同)
  • 总的来说答案很好,但我不能不同意"超过那个(2000条信息)是非常糟糕的UI"部分.一旦进入商业软件或社交网络,同一页面上的2000条信息就很常见.典型的Airbnb,Twitter,Facebook或SalesForce页面可能会处理超过2000条信息*方式*. (2认同)

MW... 320

Misko已经对数据绑定的工作原理进行了很好的描述,但我想在数据绑定的性能问题上添加我的观点.

正如Misko所说,大约2000个绑定是你开始看到问题的地方,但你不应该在一个页面上有超过2000条信息.这可能是真的,但并非每个数据绑定对用户都是可见的.一旦你开始使用双向绑定构建任何类型的小部件或数据网格,你就可以轻松地命中2000个绑定,而不会有糟糕的用户体验.

例如,考虑一个组合框,您可以在其中键入文本以过滤可用选项.这种控制可能有大约150个项目,仍然非常有用.如果它有一些额外的功能(例如当前所选选项上的特定类),则每个选项开始获得3-5个绑定.将这些小部件中的三个放在一个页面上(例如,一个用于选择国家/地区,另一个用于选择所述国家/地区的城市,第三个用于选择酒店)并且您已经介于1000到2000个绑定之间.

或者考虑企业Web应用程序中的数据网格.每页50行并不合理,每行可以有10-20列.如果使用ng-repeats构建它,和/或在某些使用某些绑定的单元格中包含信息,则可能仅使用此网格接近2000个绑定.

我发现在使用AngularJS时这是一个很大的问题,到目前为止我能找到的唯一解决方案是构建小部件而不使用双向绑定,而不是使用ngOnce,取消注册观察者和类似的技巧,或构造使用jQuery和DOM操作构建DOM的指令.我觉得这首先打败了使用Angular的目的.

我很想听听有关处理这个问题的其他方法的建议,但也许我应该写自己的问题.我想把它放在评论中,但事实证明这太长了......

TL; DR
数据绑定可能会导致复杂页面出现性能问题.

  • 是的,我是第二个.我们的应用程序的主要职责是显示不同实体之间的连接.给定页面可能包含10个部分.每个部分都有一个表格.每个表都有2-5个预先过滤器.每个表有2-5列,每列有10行.很快我们遇到了性能问题,并采用了"类似技巧"选项. (26认同)
  • 公平地说,Angular不仅仅是关于数据绑定,而且某些应用程序可能不想出于其他人引用的原因而使用此功能?我认为DI和模块化的方法本身是值得的; 拥有魔法自动绑定是很好的,但在每个现有的实现中都有性能的权衡.对于大多数CRUD网络应用而言,Angular的方式可以说是优越的,人们只是试图将其推向极端.有一个支持事件监听的替代方法会很好,但是对于单个框架来说,这可能从根本上说太复杂了? (10认同)
  • 对于阅读此内容的人来说,未来的呼声:一次绑定现在是Angular v1.3的核心功能,请在此处阅读更多内容:https://docs.angularjs.org/guide/expression (9认同)
  • Angular现在有一种方法和一次绑定数据绑定来帮助解决这个问题.此外,它现在具有转发器源的索引,允许您修改列表而无需为整个内容重建dom. (8认同)
  • @MW.老实说,我认为bind-once是核心.但它似乎不是.这只是你在编写自己的指令时可以做的事情,基本上是在没有看到它们的情况下链接东西.但是有一个ux mod:https://github.com/pasvaz/bindonce (6认同)

superluminar.. 156

通过脏检查$scope对象

Angular array$scope对象中维护着一个简单的观察者.如果你检查任何$scope你会发现它包含一个array被叫$$watchers.

每个观察者都object包含其他内容

  1. 观察者正在监视的表达.这可能只是一个attribute名字,或更复杂的东西.
  2. 表达式的最后已知值.可以根据表达式的当前计算值来检查.如果值不同,观察者将触发该功能并将其标记$scope为脏.
  3. 观察者脏的时候执行的功能.

如何定义观察者

在AngularJS中定义观察者的方法有很多种.

  • 你可以明确$watchattribute$scope.

    $scope.$watch('person.username', validateUnique);
    
  • 您可以{{}}在模板中放置插值(将在当前为您创建观察器$scope).

    <p>username: {{person.username}}</p>
    
  • 你可以问一个指令,比如ng-model为你定义观察者.

    <input ng-model="person.username" />
    

$digest循环核对其最后的值所有观察家

当我们通过正常通道(ng-model,ng-repeat等)与AngularJS交互时,指令将触发摘要周期.

摘要周期是对其所有孩子深度优先遍历$scope.对于每一个$scope object,我们迭代它$$watchers array并评估所有表达式.如果新表达式值与上一个已知值不同,则调用观察者的函数.这个函数可能会重新编译DOM的一部分,重新​​计算一个值$scope,触发一个AJAX request你需要它做的任何事情.

遍历每个范围,并根据最后一个值评估和检查每个监视表达式.

如果触发观察者,那就$scope很脏

如果触发了观察者,则应用程序知道某些内容已更改,并且$scope标记为脏.

Watcher函数可以更改$scope父级上或父级上的其他属性$scope.如果一个$watcher函数被触发,我们不能保证我们的其他函数$scope仍然是干净的,所以我们再次执行整个摘要周期.

这是因为AngularJS具有双向绑定,因此数据可以在$scope树上传回.我们可以改变$scope已经被消化的更高值.也许我们改变了一个值$rootScope.

如果$digest是脏的,我们$digest再次执行整个循环

我们不断循环遍历$digest循环,直到摘要周期清理干净(所有$watch表达式都与上一个循环中的值相同),或者我们达到摘要限制.默认情况下,此限制设置为10.

如果我们达到摘要限制,AngularJS将在控制台中引发错误:

10 $digest() iterations reached. Aborting!

摘要在机器上很难,但开发人员很容易

如您所见,每当AngularJS应用程序发生变化时,AngularJS将检查$scope层次结构中的每个观察者以查看如何响应.对于开发人员来说,这是一个巨大的生产力,因为您现在需要编写几乎没有布线代码,AngularJS会注意到值是否已更改,并使应用程序的其余部分与更改保持一致.

从机器的角度来看,虽然这种效率非常低,如果我们创造了太多的观察者,它们会减慢我们的应用程序.Misko引用了大约4000名观众的数字,之后你的应用程序在旧版浏览器上会感觉很慢.

例如,如果您ng-repeat超过大型JSON array,则很容易达到此限制.您可以使用诸如一次性绑定之类的功能来缓解此问题,以便在不创建观察者的情况下编译模板.

如何避免创建太多的观察者

每当您的用户与您的应用互动时,您应用中的每位观察者都会至少评估一次.优化AngularJS应用程序的一个重要部分是减少$scope树中观察者的数量.一种简单的方法是使用一次时间绑定.

如果您的数据很少会发生变化,您只能使用::语法将其绑定一次,如下所示:

<p>{{::person.username}}</p>

要么

<p ng-bind="::person.username"></p>

只有在呈现包含模板并加载数据时才会触发绑定$scope.

当您拥有ng-repeat许多物品时,这一点尤为重要.

<div ng-repeat="person in people track by username">
  {{::person.username}}
</div>

  • 我不同意所说的答案应该在最顶层; 知道某事并为特定问题撰写相关/详细答复之间存在差异.有更好的方法来获得赞誉.无论如何.. (4认同)
  • 很好的答案涵盖了脏检查的行为以及实际评估的内容,在Misko的回答中有一点不太清楚. (3认同)
  • 精湛而细致的答案.@superluminary,谢谢你的回答.此外,在阅读了这个答案之后,我发现我们不能将非幂等表达式添加为被观察的表达式. (3认同)

Pete BD.. 80

这是我的基本理解.这可能是错的!

  1. 通过将函数(返回要监视的东西)传递给$watch方法来监视项目.
  2. 必须在$apply方法包装的代码块内对已观看项目进行更改.
  3. 在该方法的最后,调用该方法,$apply$digest方法通过每个监视并检查自上次$digest运行以来它们是否发生了变化.
  4. 如果发现任何更改,则再次调用摘要,直到所有更改稳定为止.

在正常开发中,HTML中的数据绑定语法告诉AngularJS编译器为您创建监视,控制器方法已在内部运行$apply.所以对应用程序开发人员来说,它是透明的.

  • 何时触发apply方法? (4认同)
  • @EliseuMonar摘要循环由于某些事件或调用$ apply()而运行,它不会根据计时器定期调用.请参阅[AngularJS的$ watch功能如何工作?](http://stackoverflow.com/a/18639070/1112483)和[AngularJS中的绑定和消化如何工作?](http://stackoverflow.com/a/ 1112483分之12491335) (3认同)

jpsimons.. 61

我有一段时间自己想知道这件事.没有setter如何AngularJS注意$scope对象的变化?它会轮询它们吗?

它实际上做的是:你修改模型的任何"正常"位置都是从内部AngularJS调用的,所以它$apply会在代码运行后自动调用.假设你的控制器有一个连接到ng-click某个元素的方法.因为AngularJS将这种方法的调用连接在一起,所以它有机会$apply在适当的地方进行.同样,对于出现在视图中的表达式,这些表达式都是由AngularJS它执行的$apply.

当文档谈到必须$apply手动调用外部AngularJS代码,它正在讨论代码,这些代码在运行时不会AngularJS在调用堆栈中自行调用.


Nicolas Zozo.. 32

用图片解释:

数据绑定需要映射

范围中的引用不完全是模板中的引用.当您对两个对象进行数据绑定时,您需要第三个侦听第一个对象并修改另一个对象.

在此输入图像描述

在这里,当你修改它时<input>,你触摸data-ref3.经典的数据绑定机制将改变数据-ref4.那么其他{{data}}表达式将如何移动?

活动导致$ digest()

在此输入图像描述

角保持oldValuenewValue每一个绑定的.在每个Angular事件之后,着名的$digest()循环将检查WatchList以查看是否有更改.这些角事件ng-click,ng-change,$http完成...的$digest()意志循环,只要任何oldValue来自不同newValue.

在上一张图片中,它会注意到data-ref1和data-ref2已经改变.

结论

它有点像鸡蛋和鸡肉.你永远不知道是谁开始,但希望它能按预期大部分时间工作.

另一点是,您可以轻松理解简单绑定对内存和CPU的影响.希望桌面足够肥胖来处理这个问题.手机并不那么强大.


Sasank Sunka.. 22

显然,没有定期检查Scope附加到它的对象是否有任何变化.并非所有附加到范围的对象都被观看.范围原型维持一个观察者.Scope只有$$watchers$digest调用时才会遍历这个.

Angular为这些观众添加了观察者

  1. {{表达式}} - 在您的模板中(以及其他有表达式的地方)或我们定义ng-model时.
  2. $ scope.$ watch('expression/function') - 在你的JavaScript中我们可以附加一个范围对象来观察角度.

$ watch函数有三个参数:

  1. 第一个是观察者函数,它只返回对象,或者我们可以添加一个表达式.

  2. 第二个是侦听器函数,当对象发生更改时将调用该函数.DOM更改等所有内容都将在此函数中实现.

  3. 第三个是一个可选参数,它接受一个布尔值.如果它是真的,有角度的深度观察对象&如果它的假角度只是做一个参考观察对象.$ watch的粗略实现看起来像这样

Scope.prototype.$watch = function(watchFn, listenerFn) {
   var watcher = {
       watchFn: watchFn,
       listenerFn: listenerFn || function() { },
       last: initWatchVal  // initWatchVal is typically undefined
   };
   this.$$watchers.push(watcher); // pushing the Watcher Object to Watchers  
};

Angular中有一个有趣的东西叫做Digest Cycle.$ digest循环由于调用$ scope而开始.$ digest().假设您通过ng-click指令更改处理函数中的$ scope模型.在这种情况下,AngularJS通过调用$ digest()自动触发$ digest循环.除了ng-click之外,还有其他一些内置指令/服务可以让你改变模型(例如ng-model,$ timeout等)并自动触发$摘要周期.$ digest的粗略实现看起来像这样.

Scope.prototype.$digest = function() {
      var dirty;
      do {
          dirty = this.$$digestOnce();
      } while (dirty);
}
Scope.prototype.$$digestOnce = function() {
   var self = this;
   var newValue, oldValue, dirty;
   _.forEach(this.$$watchers, function(watcher) {
          newValue = watcher.watchFn(self);
          oldValue = watcher.last;   // It just remembers the last value for dirty checking
          if (newValue !== oldValue) { //Dirty checking of References 
   // For Deep checking the object , code of Value     
   // based checking of Object should be implemented here
             watcher.last = newValue;
             watcher.listenerFn(newValue,
                  (oldValue === initWatchVal ? newValue : oldValue),
                   self);
          dirty = true;
          }
     });
   return dirty;
 };

如果我们使用JavaScript的setTimeout()函数来更新范围模型,Angular无法知道您可能会更改什么.在这种情况下,我们有责任手动调用$ apply(),这会触发$ digest循环.同样,如果您有一个设置DOM事件侦听器的指令并更改处理函数内的某些模型,则需要调用$ apply()以确保更改生效.$ apply的主要思想是我们可以执行一些不了解Angular的代码,该代码可能仍会改变范围内的东西.如果我们将该代码包装在$ apply中,它将负责调用$ digest().$ apply()的粗略实现.

Scope.prototype.$apply = function(expr) {
       try {
         return this.$eval(expr); //Evaluating code in the context of Scope
       } finally {
         this.$digest();
       }
};


Bharath Kuma.. 15

有三个强大的功能帮助AngularJS手柄的数据绑定机制: $腕表() ,)$摘要($应用() .大多数情况下,AngularJS将调用$ scope.$ watch()和$ scope.$ digest(),但在某些情况下,您可能需要手动调用这些函数以使用新值进行更新.

$ watch(): -

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

$ digest() -

此函数遍历$ scope对象中的所有监视及其子$ scope对象
(如果有).当$ digest()遍历监视时,它会检查表达式的值是否已更改.如果值已更改,AngularJS将使用新值和旧值调用侦听器.只要AngularJS认为有必要,就会调用$ digest()函数.例如,在单击按钮之后,或在AJAX调用之后.在某些情况下,AngularJS不会为您调用$ digest()函数.在这种情况下,你必须自己调用它.

$ apply() -

Angular会自动神奇地更新AngularJS上下文中的那些模型更改.当您更改Angular上下文之外的任何模型(如浏览器DOM事件,setTimeout,XHR或第三方库)时,您需要通过手动调用$ apply()来通知Angular更改.当$ apply()函数调用完成时,AngularJS在内部调用$ digest(),因此所有数据绑定都会更新.


小智.. 7

碰巧我需要将人的数据模型与表单链接起来,我所做的是将数据与表单直接映射.

例如,如果模型有类似于:

$scope.model.people.name

表格的控制输入:

<input type="text" name="namePeople" model="model.people.name">

这样,如果修改对象控制器的值,这将在视图中自动反映出来.

我通过模型的示例是从服务器数据更新的,当您要求邮政编码和基于书面加载的邮政编码时,与该视图关联的殖民地和城市列表,默认情况下为用户设置第一个值.而且我工作得很好,发生了什么,angularJS有时需要几秒钟来刷新模型,为此你可以在显示数据的同时放置一个微调器.

  • 我读了5次这个答案,我仍然不明白这里是什么意思. (14认同)

小智.. 6

  1. 单向数据绑定是一种方法,其中从数据模型中获取值并将其插入到HTML元素中.无法从视图更新模型.它用于经典模板系统.这些系统仅在一个方向上绑定数据.

  2. Angular应用程序中的数据绑定是模型和视图组件之间数据的自动同步.

通过数据绑定,您可以将模型视为应用程序中的单一事实来源.视图始终是模型的投影.如果模型已更改,则视图会反映更改,反之亦然.


AllJs.. 5

这是一个使用输入字段与AngularJS进行数据绑定的示例。我会在后面解释

HTML代码

<div ng-app="myApp" ng-controller="myCtrl" class="formInput">
     <input type="text" ng-model="watchInput" Placeholder="type something"/>
     <p>{{watchInput}}</p> 
</div>

AngularJS代码

myApp = angular.module ("myApp", []);
myApp.controller("myCtrl", ["$scope", function($scope){
  //Your Controller code goes here
}]);

正如你可以在上面的例子中看到,AngularJS用途ng-model聆听和观看HTML元素会发生什么,尤其是在input各个领域。当某事发生时,做某事。在我们的案例中,ng-model使用髭标记绑定到我们的视图{{}}。输入字段中键入的任何内容都会立即显示在屏幕上。这就是使用最简单形式的AngularJS进行数据绑定的好处。

希望这可以帮助。

Codepen上查看工作示例


ojus kulkarn.. 5

AngularJs支持双向数据绑定
意味着您可以访问数据View-> ControllerController-> View

对于前

1)

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

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

O / P

Peter

您可以ng-model像这样绑定数据:
-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>

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

$scope.name = {};

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

ng-model绑定我们的视图并将其呈现为expression {{ }}
ng-model是在视图中向用户显示并与用户进行交互的数据。
因此在AngularJs中绑定数据很容易。


归档时间:

查看次数:

342441 次

最近记录:

1 年,11 月 前