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+css+ul模拟列表菜单具体实现思路
Apr 15 Javascript
纯JS实现根据CSS的class选择DOM
Mar 22 Javascript
JQuery each()嵌套使用小结
Apr 18 Javascript
纯js实现遮罩层效果原理分析
May 27 Javascript
微信中一些常用的js方法汇总
Mar 12 Javascript
js实现带圆角的多级下拉菜单效果
Aug 28 Javascript
使用Promise解决多层异步调用的简单学习心得
May 17 Javascript
window.open打开窗口被拦截的快速解决方法
Aug 04 Javascript
分享javascript、jquery实用代码段
Oct 20 Javascript
js上下视差滚动简单实现代码
Mar 07 Javascript
微信小程序保存图片到相册权限设置
Apr 09 Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
Aug 26 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
php二维数组排序方法(array_multisort usort)
2013/12/25 PHP
php计算到指定日期还有多少天的方法
2015/04/14 PHP
在WordPress中实现评论头像的自定义默认和延迟加载
2015/11/24 PHP
PHP5.2中PDO的简单使用方法
2016/03/25 PHP
PHP页面输出时js设置input框的选中值
2016/09/30 PHP
php中namespace及use用法分析
2016/12/06 PHP
PHP基于SMTP协议实现邮件发送实例代码
2017/04/27 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
用javascript实现页面打印的三种方法
2007/03/05 Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
2010/10/20 Javascript
仿微博字符限制效果实现代码
2012/04/20 Javascript
js/jquery判断浏览器类型的方法小结
2015/05/12 Javascript
JavaScript基本数据类型及值类型和引用类型
2015/08/25 Javascript
Bootstrap 粘页脚效果
2016/03/28 Javascript
js实现商品抛物线加入购物车特效
2020/11/18 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
JS实现数组去重方法总结(六种方法)
2017/07/14 Javascript
React-Router如何进行页面权限管理的方法
2017/12/06 Javascript
Vue中的v-for指令不起效果的解决方法
2018/09/27 Javascript
微信运维交互机器人的示例代码
2018/11/12 Javascript
JavaScript实现矩形块大小任意缩放
2020/08/25 Javascript
在Python中marshal对象序列化的相关知识
2015/07/01 Python
python遍历小写英文字母的方法
2019/01/02 Python
Python合并同一个文件夹下所有PDF文件的方法
2019/03/11 Python
PYQT5实现控制台显示功能的方法
2019/06/25 Python
命令行运行Python脚本时传入参数的三种方式详解
2019/10/11 Python
Python中包的用法及安装
2020/02/11 Python
使用Html5多媒体实现微信语音功能
2019/07/26 HTML / CSS
保安员岗位职责
2013/11/17 职场文书
军训 自我鉴定
2014/02/03 职场文书
仓库管理员岗位职责
2014/03/19 职场文书
竞选大队委员演讲稿
2014/04/28 职场文书
党建工作汇报材料
2014/12/24 职场文书
学雷锋活动简报
2015/07/20 职场文书
详解Mysql数据库平滑扩容解决高并发和大数据量问题
2022/05/25 MySQL