angularjs 的数据绑定实现原理


Posted in Javascript onJuly 02, 2018

在angularjs1.X 中存在了三种数据绑定的方式,用于数据的同步、展示。在 angularjs 1.3 之前,angularjs 只存在两种方式: two-way-binding 和 one-way-bindng , 而后则引入了称为one-time-binding 的绑定机制。

目前angularjs 中存在以下三种数据绑定方式:

  1. two-way-binding
  2. one-way-binding
  3. one-time-binding

two-way-binding

angularjs 中的 Two-way-binding 的作用是将 Model 和 View 关联起来,任何一侧的数据变更都会更新另一侧的数据。

常见场景是页面中的输入区域。双向绑定可以很容易的将输入控件的值关联到数据模型中。

<input type="text" id="text" ng-model="name"/>

通过 ng-model 我们可以很容易的将输入框(view)的值和 name (Model) 关联起来。在双向数据流的作用下,无论是我们修改输入框的值还是修改 name,另外一侧都将及时更新到新数据。

ng-model 是 angularjs 内置的一个指令用来实现双向绑定。ng-model 在不同生命周期中,有不同的逻辑处理。

1、compilation phase:

  • ng-model 指令和 input 指令会被合并处理给 input 标签 注册 keydown事件(DOM Event);
  • interpolation 则注册一个 $watch 用来订阅 change 事件(angularjs Event)。

2、Runtime Phase

  • 用户输入触发 keydown
  • input 指令捕获 keydown 事件,调用 $apply 来请求更新动作。
  • angularjs 更新值到 Model
  • 进入 $digest 上下文
  • $watch 表达式检测到 Model 发生了 change,通知interpolation ,请求 更新 DOM。
  • angularjs 托管结束,退出托管,交还控制权到 JavaScript 执行上下文。
  • 最后浏览器重新渲染文本。

One-way-binding

不同于 Two-way-binding的双向流动, one-way-binding 的数据流向是单向,即只会从 model 流向 view ,而不会从 view 流向 model。 因此, one-way-binding 用来展示数据,而不是获取输入。

在 angularjs 中, one-way-binding 则有两种语法: ng-bind 和 {{expression}}。

<span ng-bind="name"> </span>
<span>{{name}}</span>

对于 one-way-binding来说,内部机制和 two-way-binding 有部分相同的机制。

1、compilation phase:

  1. interpolation 注册一个 $watch 用来订阅 change 事件(angularjs Event)。

2、runtime phase:

  1. angularjs 进入 $digest 。
  2. expression 的 $watch 检测到数据发生变更,通知interpolation ,请求 更新 DOM。
  3. angularjs 托管结束,退出托管,交还控制权到 JavaScript 执行上下文。
  4. 最后浏览器重新渲染文本。

one-time-binding

1.3 之后,angularjs 实现了一个叫 one-time-binding 的机制。本质上它的机制和其他两种方式没太多差异,但在数据更新时候表现的不太一样。

one-time-binding 同样会注册 $watch 来监听数据变化,但它会在第一次检测到数据 非 Undefined 时候取消监听。

<span>{{::name}}</span>

对于上面的代码,假设 name 从 undefined -> angularjs -> angular ,最终渲染的结果是 angularjs ,而不是 angular 。 这就是 one-time-binding 的特殊之处,当 name 从 undefined 变化为 angularjs之后,被认定为 name 的状态已经是 stable ,因此将取消 $watch , 即不再监听数据变化。

那么,假设 name 从 '' -> angularjs-> angular, 则渲染结果是 '' ,即空字符串(第一次的值)。因为 one-time-binding 在计算 stable 时候使用的 严格相等,即 newVal === undefined, 如果是,则继续保留 $watch 等待下一次的比较;否则,状态变更为 stable,取消 $watch, 数据转化为最终态。

结束

在我看来,angularjs 核心在于 angularjs context 和 $digest 。

angularjs context 保证 angularjs 可以捕获到各种事件,用户输入、鼠标事件、键盘事件、甚至 $settimeout和 $http 等异步行为的状态流转。

而 $digest 则保证 angularjs 可以确认是否要更新数据。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery插件之打造自定义的select标签
Nov 30 Javascript
分享20款美化网站的 jQuery Lightbox 灯箱插件
Oct 10 Javascript
JavaScript实现将文本框的值插入指定位置的方法
Aug 13 Javascript
Jquery promise实现一张一张加载图片
Nov 13 Javascript
一种新的javascript对象创建方式Object.create()
Dec 28 Javascript
bootstrap实现弹窗和拖动效果
Jan 03 Javascript
JavaScript中绑定事件的三种方式及去除绑定
Nov 05 Javascript
原生JS实现跑马灯效果
Feb 20 Javascript
10道典型的JavaScript面试题
Mar 22 Javascript
深入理解Javascript中的作用域链和闭包
Apr 25 Javascript
JS 组件系列之Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案
Jun 30 Javascript
简单了解JS打开url的方法
Feb 21 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
Jul 02 #Javascript
vue中的数据绑定原理的实现
Jul 02 #Javascript
Vue实现双向绑定的原理以及响应式数据的方法
Jul 02 #Javascript
jsonp跨域获取数据的基础教程
Jul 01 #Javascript
vue + webpack如何绕过QQ音乐接口对host的验证详解
Jul 01 #Javascript
关于Vue组件库开发详析
Jul 01 #Javascript
D3.js实现拓扑图的示例代码
Jun 30 #Javascript
You might like
用DBSQL类加快开发MySQL数据库程序的速度
2006/10/09 PHP
PHP生成月历代码
2007/06/14 PHP
php随机显示图片的简单示例
2014/02/15 PHP
解决laravel session失效的问题
2019/10/14 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
2020/02/16 PHP
基于jQuery的可以控制左右滚动及自动滚动效果的代码
2010/07/25 Javascript
几种延迟加载JS代码的方法加快网页的访问速度
2013/10/12 Javascript
js实现表单检测及表单提示的方法
2015/08/14 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
关于JS中setTimeout()无法调用带参函数问题的解决方法
2016/06/21 Javascript
Bootstrap CSS组件之大屏幕展播
2016/12/17 Javascript
bootstrap jquery dataTable 异步ajax刷新表格数据的实现方法
2017/02/10 Javascript
微信小程序开发之animation循环动画实现的让云朵飘效果
2017/07/14 Javascript
微信小程序在其他页面监听globalData中值的变化
2019/07/15 Javascript
[06:53]2018DOTA2国际邀请赛寻真——勇于创新的Vici Gaming
2018/08/14 DOTA
把大数据数字口语化(python与js)两种实现
2013/02/21 Python
Python实现远程调用MetaSploit的方法
2014/08/22 Python
使用Python脚本操作MongoDB的教程
2015/04/16 Python
python队列通信:rabbitMQ的使用(实例讲解)
2017/12/22 Python
基于Python的PIL库学习详解
2019/05/10 Python
移动Web—CSS为Retina屏幕替换更高质量的图片
2012/12/24 HTML / CSS
Vans英国官方网站:美国南加州的原创极限运动潮牌
2017/01/20 全球购物
Michael Kors香港官网:美国奢侈品品牌
2019/12/26 全球购物
JD Sports澳洲官网:英国领先的运动鞋和运动时尚零售商
2020/02/15 全球购物
会计系毕业个人自荐信格式
2013/09/23 职场文书
中学老师的自我评价
2013/11/07 职场文书
母婴店促销方案
2014/03/05 职场文书
外语专业毕业生自荐信
2014/04/14 职场文书
乡镇安全生产目标责任书
2014/07/23 职场文书
个人授权委托书范本格式
2014/10/12 职场文书
2014年销售工作总结范文
2014/12/01 职场文书
2015年12.4全国法制宣传日活动总结
2015/03/24 职场文书
考试没考好检讨书
2015/05/06 职场文书
2016新年致辞
2015/08/01 职场文书
新店开业策划方案怎么书写?
2019/07/05 职场文书
Android Flutter实现3D动画效果示例详解
2022/04/07 Java/Android