AngularJS 工作原理详解


Posted in Javascript onAugust 18, 2016

 个人觉得,要很好的理解AngularJS的运行机制,才能尽可能避免掉到坑里面去。在这篇文章中,我将根据网上的资料和自己的理解对AngularJS的在启动后,每一步都做了些什么,做一个比较清楚详细的解析。
     首先上一小段代码(index.html),结合代码我们来看看,angular一步一步都做了些什么。

<!doctype html>
<html ng-app>
 <head>
 <script src="angular.js"></script>
 </head>
 <body>
 <png-init=" name='World' ">Hello {{name}}!</p>
 </body> 
</html>

当你用浏览器去访问index.html的时候,浏览器依次做了如下一些事情:

  1. 加载html,然后解析成DOM;
  2. 加载angular.js脚本;
  3. AngularJS等待DOMContentLoaded事件的触发;
  4. AngularJS寻找ng-app指令,根据这个指令确定应用程序的边界;
  5. 使用ng-app中指定的模块配置$injector;
  6. 使用$injector创建$compile服务和$rootScope;
  7. 使用$compile服务编译DOM并把它链接到$rootScope上;
  8. ng-init指令对scope里面的变量name进行赋值;
  9. 对表达式{{name}}进行替换,于是乎,显示为“Hello World!”    

整个过程可以用这张图来表示:

AngularJS 工作原理详解

 好了,通过上面的例子我们清楚了AngularJS是怎样一步一步渲染出一个页面的。那么它又是如何和浏览器的事件回路来交互的呢?或者说是如何跟用户来交互的呢?粗略来讲,主要分为三个阶段:

1.  浏览器的事件回路一直等待着事件的触发,事件包括用户的交互操作、定时事件或者网络事件(如服务器的响应等);

2.  一旦有事件触发,就会进入到Javascript的context中,一般通过回调函数来修改DOM;

3.  等到回调函数执行完毕之后,浏览器又根据新的DOM来渲染新的页面。

     正如下面一张图所示,交互过程主要由几个循环组成:

AngularJS 工作原理详解

AngularJS修改了一般的Javascript工作流,并且提供了它自己的事件处理机制。这样就把Javascript的context分隔成两部分,一部分是原生的Javascript的context,另一部分是AngularJS的context。只有处在AngularJS的context中的操作才能享受到Angular的data-binding、exception handling、property watching等服务,但是对于外来者(如原生的Javascript操作、自定义的事件回调、第三方的库等)Angular也不是一概不接见,可以使用AngularJS提供的$apply()函数将这些外来者包进AngularJS的context中,让Angular感知到他们产生的变化。

     接下来,让我们一起来看看交互过程中的这几个循环是怎么工作的?

1.  首先,浏览器会一直处于监听状态,一旦有事件被触发,就会被加到一个event queue中,event queue中的事件会一个一个的执行。

2.  event queue中的事件如果是被$apply()包起来的话,就会进入到AngularJS的context中,这里的fn()是我们希望在AngularJS的context中执行的函数。

3.  AngularJS将执行fn()函数,通常情况下,这个函数会改变应用的某些状态。

4.  然后AngularJS会进入到由两个小循环组成的$digest循环中,一个循环是用来处理$evalAsync队列(用来schedule一些需要在渲染视图之前处理的操作,通常通过setTimeout(0)实现,速度会比较慢,可能会出现视图抖动的问题)的,一个循环是处理$watch列表(是一些表达式的集合,一旦有改变发生,那么$watch函数就会被调用)的。$digest循环会一直迭代知道$evalAsync队列为空并且$watch列表也为空的时候,即model不再有任何变化。

5.  一旦AngularJS的$digest循环结束,整个执行就会离开AngularJS和Javascript的context,紧接着浏览器就会把数据改变后的视图重新渲染出来。

     接下来,我们还是结合代码来解析一下:

<!doctype html>
<html ng-app>
 <head>
 <script src="angular.js"></script>
 </head>
 <body>
 <input ng-model="name">
 <p>Hello {{name}}!</p>
 </body> 
</html>

  这段代码和上一段代码唯一的区别就是有了一个input来接收用户的输入。在用浏览器去访问这个html文件的时候,input上的ng-model指令会给input绑上keydown事件,并且会给name变量建议一个$watch来接收变量值改变的通知。在交互阶段主要会发生以下一系列事件:

1.  当用户按下键盘上的某一个键的时候(比如说A),触发input上的keydown事件;

2.  input上的指令察觉到input里值的变化,调用$apply(“name=‘A'”)更新处于AngularJS的context中的model;

3.  AngularJS将'A'赋值给name;

4.  $digest循环开始,$watch列表检测到name值的变化,然后通知{{name}}表达式,更新DOM;

5.  退出AngularJS的context,然后退出Javascript的context中的keydown事件;

6.  浏览器重新渲染视图。

以上就是对AngularJS 工作原理的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

Javascript 相关文章推荐
jquery提示 &quot;object expected&quot;的解决方法
Dec 13 Javascript
jquery lazyload延迟加载技术的实现原理分析
Jan 24 Javascript
Prototype源码浅析 String部分(一)之有关indexOf优化
Jan 15 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
Jul 10 Javascript
javascript实现数组中的内容随机输出
Aug 11 Javascript
快速掌握Node.js中setTimeout和setInterval的使用方法
Mar 21 Javascript
JavaScript代码实现左右上下自动晃动自动移动
Apr 08 Javascript
浅谈JS的基础类型与引用类型
Sep 13 Javascript
js实现打地鼠小游戏
Feb 13 Javascript
vue路由守卫及路由守卫无限循环问题详析
Sep 05 Javascript
vue中动态select的使用方法示例
Oct 28 Javascript
leaflet加载geojson叠加显示功能代码
Feb 21 Javascript
js H5 canvas投篮小游戏
Aug 18 #Javascript
jQuery过滤选择器经典应用
Aug 18 #Javascript
jQuery表单事件实例代码分享
Aug 18 #Javascript
Angularjs结合Bootstrap制作的一个TODO List
Aug 18 #Javascript
AngularJS 执行流程详细介绍
Aug 18 #Javascript
AngularJS国际化详解及示例代码
Aug 18 #Javascript
ECMAScript6轮播图实践知识总结
Aug 17 #Javascript
You might like
Netflix将与CLAMP、乙一以及冲方丁等6名知名制作人合伙展开原创动画计划!
2020/03/06 日漫
短波收音机简介
2021/03/01 无线电
基于数据库的在线人数,日访问量等统计
2006/10/09 PHP
php正则校验用户名介绍
2008/07/19 PHP
php中的注释、变量、数组、常量、函数应用介绍
2012/11/16 PHP
PHP之uniqid()函数用法
2014/11/03 PHP
php获取本周星期一具体日期的方法
2015/04/20 PHP
phpstorm 正则匹配删除空行、注释行(替换注释行为空行)
2018/01/21 PHP
javascript让setInteval里的函数参数中的this指向特定的对象
2010/01/31 Javascript
基于jquery的滑动样例代码
2010/11/20 Javascript
Jquery截取中文字符串的实现代码
2010/12/22 Javascript
通过jquery的$.getJSON做一个跨域ajax请求试验
2011/05/03 Javascript
浅析JavaScript基本类型与引用类型
2014/05/28 Javascript
JavaScript模版引擎的基本实现方法浅析
2016/02/15 Javascript
JQuery插件Marquee.js实现无缝滚动效果
2016/04/26 Javascript
js判断radiobuttonlist的选中值显示/隐藏其它模块的实现方法
2016/08/25 Javascript
JQuery手速测试小游戏实现思路详解
2016/09/20 Javascript
Javascript农历与公历相互转换的简单实例
2016/10/09 Javascript
js获取指定字符前/后的字符串简单实例
2016/10/27 Javascript
Bootstrap免费字体和图标网站(值得收藏)
2017/03/16 Javascript
使用D3.js+Vue实现一个简单的柱形图
2018/08/05 Javascript
微信小程序自定义组件实现环形进度条
2020/11/17 Javascript
Python编程中对文件和存储器的读写示例
2016/01/25 Python
Python基础教程之tcp socket编程详解及简单实例
2017/02/23 Python
Python数据结构之哈夫曼树定义与使用方法示例
2018/04/22 Python
python 读取竖线分隔符的文本方法
2018/12/20 Python
python实现简单加密解密机制
2019/03/19 Python
python二进制读写及特殊码同步实现详解
2019/10/11 Python
银行实习人员自我鉴定
2013/09/22 职场文书
总经理任命书范本
2014/06/05 职场文书
感恩老师演讲稿600字
2014/08/28 职场文书
法定授权委托证明书
2014/09/27 职场文书
工作骂脏话检讨书
2014/10/05 职场文书
2015年领导干部廉洁自律工作总结
2015/05/26 职场文书
人生一定要学会的三样东西:放下、忘记、珍惜
2019/08/21 职场文书
MySQL into_Mysql中replace与replace into用法案例详解
2021/09/14 MySQL