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 相关文章推荐
浅说js变量
May 25 Javascript
javascript生成随机数的方法
May 16 Javascript
被遗忘的javascript的slice() 方法
Apr 20 Javascript
解决JS请求服务器gbk文件乱码的问题
Oct 16 Javascript
Bootstrap与Angularjs的模态框实例代码
Aug 03 Javascript
安装vue-cli报错 -4058 的解决方法
Oct 19 Javascript
使用vue实现grid-layout功能实例代码
Jan 05 Javascript
vue初尝试--项目结构(推荐)
Jan 30 Javascript
使用微信小程序开发弹出框应用实例详解
Oct 18 Javascript
VUE接入腾讯验证码功能(滑块验证)备忘
May 07 Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
May 30 Javascript
解决在layer.open中使用时间控件laydate失败的问题
Sep 11 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
采用header定义为文件然后readfile下载(隐藏下载地址)
2014/01/31 PHP
zf框架db类的分页示例分享
2014/03/14 PHP
深入浅析php中sprintf与printf函数的用法及区别
2016/01/08 PHP
php短信接口代码
2016/05/13 PHP
php微信高级接口调用方法(自定义菜单接口、客服接口、二维码)
2016/11/28 PHP
PHP编程计算文件或数组中单词出现频率的方法
2017/05/22 PHP
Laravel框架表单验证操作实例分析
2019/09/30 PHP
js实现收缩菜单效果实例代码
2013/10/30 Javascript
Javascript中封装window.open解决不兼容问题
2014/09/28 Javascript
js与jquery实时监听输入框值的oninput与onpropertychange方法
2015/02/05 Javascript
JavaScript的RequireJS库入门指南
2015/07/01 Javascript
Javascript连接Access数据库完整实例
2015/08/03 Javascript
js判断手机号运营商的方法
2015/10/23 Javascript
简单实现JS对dom操作封装
2015/12/02 Javascript
js实现文本框输入文字个数限制代码
2015/12/25 Javascript
基于JavaScript将表单序列化类型的数据转化成对象的处理(允许对象中包含对象)
2015/12/28 Javascript
js addDqmForPP给标签内属性值加上双引号的函数
2016/12/24 Javascript
微信小程序 picker 组件详解及简单实例
2017/01/10 Javascript
微信小程序之MaterialDesign--input组件详解
2017/02/15 Javascript
javascript简单写的判断电话号码实例
2017/05/24 Javascript
Vue.js如何实现路由懒加载浅析
2017/08/14 Javascript
Angular 实现输入框中显示文章标签的实例代码
2018/11/07 Javascript
python生成器,可迭代对象,迭代器区别和联系
2018/02/04 Python
对python中使用requests模块参数编码的不同处理方法
2018/05/18 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
python 对给定可迭代集合统计出现频率,并排序的方法
2018/10/18 Python
python实现二维插值的三维显示
2018/12/17 Python
Python常用爬虫代码总结方便查询
2019/02/25 Python
Python通过文本和图片生成词云图
2020/05/21 Python
Old Navy加拿大官网:美式休闲服饰品牌
2017/09/26 全球购物
大学生毕业自我鉴定范文
2013/11/03 职场文书
商务日语毕业生自荐信
2013/11/23 职场文书
真诚的求职信
2014/07/04 职场文书
如何写好开幕词?
2019/06/24 职场文书
一文带你理解vue创建一个后台管理系统流程(Vue+Element)
2021/05/18 Vue.js
利用JuiceFS使MySQL 备份验证性能提升 10 倍
2022/03/17 MySQL