Angular数据绑定机制原理


Posted in Javascript onApril 17, 2018

1.Angular.js扩展浏览器的事件循环

浏览器持续等待例如用户交互这样的事件。当你在一个<input>标签里输入字符之后,这个事件的回调函数在JS解释器中执行了其包含的DOM操作,执行完毕后,浏览器响应地对DOM做出了变化。Angular拓展了这个事件循环,使它有时候成为angular context 的执行环境。

2.$watch list

$watch 可以检测model的变化。每当绑定一个数据到view上的时候,$watch队列就会插入一条对应的$watch。例子如下:

controller.js:

app.controller('MainCtrl', function($scope) {
 $scope.people = [...]; // 假设长度为10
});

index.html:

<ul>
 <li ng-repeat="person in people">
   {{person.name}} - {{person.age}}
 </li>
</ul>

其中ng-repeat 生成了一个1个$watch,每个person生成了2个$watch,总共是(1+2*10),21个$watch。$watch的生成阶段是模板加载完成,也就是linking阶段。(angular分为compile和linking阶段),Angular会寻找每个directive(上面的例子中ng-repeat和{{}}都属于directive),然后生成每个$watch。

3.$digest 循环

当浏览器接收到angular context相关的事件时,$digest循环就会被触发。它由2个小循环组成,1个处理evalAsync 队列,另一个处理$watch队列。$digest进行循环时,将遍历$watch队列,查看是否有数据更新过,这种遍历就叫做dirty-checkin(脏检查),如果脏检查发现有$watch更新,将会触发新的脏检查,直到所有的$watch都没有更新。这样就能保证每个model都不会变化。

脏检查超过10次后会抛出异常防止无限循环。$digest循环结束后DOM会相应地发生变化。其实$digest从字面意义理解就像“消化”的过程一样,逐渐地把所有营养($watch的变化)都吸收掉。

4.通过$apply 进入 angular context

$apply 决定事件是否进入angular context,使用angualr的自带directive,比如ng-model,更改绑定的数据时,angular会将事件封装到$apply中。比如,ng-model="name"的输入框,输入字符“w”,事件会调用,$apply("name='w';"),完成$scope中的数据更新。

调用第三方库时的数据绑定

当在angular中调用jquery,并不能更新jquery绑定的数据,因为jquery没有调用$apply,事件没有进入angular context,导致$digest没有执行。例子如下:

app.js

app.directive('clickable', function() {
  return {
   restrict: "E",
   scope: {
    count1: '=',
    count2: '='
   },
   template: '<ul style="background-color: lightblue"><li>{{count1}}</li><li>{{count2}}</li></ul>',
   link: function(scope, element, attrs) {
    element.bind('click', function() {
     scope.count1++;
     scope.count2++;
    });
   }
  }
});
app.controller('MainCtrl', function($scope) {
 $scope.count1= 0;
 $scope.count2= 0;
});

例子中,每次点击该元素,预期count1和count2都会自增1,但实际没有。其实$scope(ViewModel)已经改变,但是没有强制执行$digest。修改click事件如下:

element.bind('click', function() {
 scope.$apply(function() {
   scope.foo++;
   scope.bar++;
 });
})

经过调用$apply实现了预期。

5.总结

angular事件绑定机制如下图:

Angular数据绑定机制原理

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

Javascript 相关文章推荐
Prototype使用指南之string.js
Jan 10 Javascript
js不能获取隐藏的div的宽度只能先显示后获取
Sep 04 Javascript
浅谈JavaScript中的Math.atan()方法的使用
Jun 14 Javascript
图解JavaScript中的this关键字
May 28 Javascript
源码分析Vue.js的监听实现教程
Apr 23 Javascript
Angular4.0中引入laydate.js日期插件的方法教程
Dec 25 Javascript
JS实现的JSON数组去重算法示例
Apr 11 Javascript
vue项目中api接口管理总结
Apr 20 Javascript
详解在create-react-app使用less与antd按需加载
Dec 06 Javascript
vue实现图片懒加载的方法分析
Feb 05 Javascript
vue实现图片上传功能
May 28 Javascript
详解Js模块化的作用原理和方案
Apr 29 Javascript
基于vue-ssr的静态网站生成器VuePress 初体验
Apr 17 #Javascript
jQuery实现使用sort方法对json数据排序的方法
Apr 17 #jQuery
jQuery+datatables插件实现ajax加载数据与增删改查功能示例
Apr 17 #jQuery
jQuery实现带右侧索引功能的通讯录示例【附源码下载】
Apr 17 #jQuery
Angular 容器部署的方法
Apr 17 #Javascript
bootstrap中日历范围选择插件daterangepicker的使用详解
Apr 17 #Javascript
jQuery简单判断值是否存在于数组中的方法示例
Apr 17 #jQuery
You might like
2020显卡排行榜天梯图 显卡天梯图2020年3月最新版
2020/04/02 数码科技
ThinkPHP3.1新特性之动态设置自动完成及自动验证示例代码
2014/06/23 PHP
php过滤HTML标签、属性等正则表达式汇总
2014/09/22 PHP
php中Ctype函数用法详解
2014/12/09 PHP
php微信高级接口群发 多客服
2016/06/23 PHP
thinkphp5 加载静态资源路径与常量的方法
2017/12/24 PHP
laravel ORM 只开启created_at的几种方法总结
2018/01/29 PHP
PHP有序表查找之二分查找(折半查找)算法示例
2018/02/09 PHP
thinkphp5+layui实现的分页样式示例
2019/10/08 PHP
javascript vvorld 在线加密破解方法
2008/11/13 Javascript
jQuery实现HTML5 placeholder效果实例
2014/12/09 Javascript
javascript使用for循环批量注册的事件不能正确获取索引值的解决方法
2014/12/20 Javascript
javascript replace()第二个参数为函数时的参数用法
2016/12/26 Javascript
JS实现简单抖动效果
2017/06/01 Javascript
Javascript格式化并高亮xml字符串的方法及注意事项
2018/08/13 Javascript
Vue两个版本的区别和使用方法(更深层次了解)
2020/02/16 Javascript
vue+element_ui上传文件,并传递额外参数操作
2020/12/05 Vue.js
[00:32]2018DOTA2亚洲邀请赛OpTic出场
2018/04/03 DOTA
[51:53]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第二场 11.01
2020/11/02 DOTA
深入理解Python中的元类(metaclass)
2015/02/14 Python
Python远程方法调用实现过程解析
2020/07/28 Python
python把一个字符串切开的实例方法
2020/09/27 Python
python 通过pip freeze、dowload打离线包及自动安装的过程详解(适用于保密的离线环境
2020/12/14 Python
HTML5获取当前地理位置并在百度地图上展示的实例
2020/07/10 HTML / CSS
HTML5 video循环播放多个视频的方法步骤
2020/08/06 HTML / CSS
MCAKE蛋糕官方网站:一直都是巴黎的味道
2018/02/06 全球购物
char型变量中能不能存贮一个中文汉字
2015/07/08 面试题
企业标语口号
2014/06/10 职场文书
标准单位租车协议书
2014/09/23 职场文书
学校运动会报道稿
2014/09/23 职场文书
2015年党员公开承诺书范文
2015/01/22 职场文书
大学军训决心书
2015/02/05 职场文书
2016年秋季开学典礼新闻稿
2015/11/25 职场文书
导游词之杭州西湖
2019/09/19 职场文书
golang如何去除多余空白字符(含制表符)
2021/04/25 Golang
用Python实现一个打字速度测试工具来测试你的手速
2021/05/28 Python