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 相关文章推荐
javascript attachEvent绑定多个事件执行顺序问题
Oct 20 Javascript
IE6下focus与blur错乱的解决方案
Jul 31 Javascript
JavaScript加强之自定义event事件
Sep 21 Javascript
js与jQuery 获取父窗、子窗的iframe
Dec 20 Javascript
ECMAScript5中的对象存取器属性:getter和setter介绍
Dec 08 Javascript
jQuery结合HTML5制作的爱心树表白动画
Feb 01 Javascript
JavaScript判断FileUpload控件上传文件类型
Sep 28 Javascript
深入浅析JavaScript字符串操作方法 slice、substr、substring及其IE兼容性
Dec 16 Javascript
JavaScript实现获取某个元素相邻兄弟节点的prev与next方法
Jan 25 Javascript
BootStrap使用file-input插件上传图片的方法
Sep 05 Javascript
js获取当前时间(昨天、今天、明天)
Nov 23 Javascript
jquery获取input type=text中的值的各种方式(总结)
Dec 02 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
第十二节--类的自动加载
2006/11/16 PHP
用php实现的下载css文件中的图片的代码
2010/02/08 PHP
PHP5中Cookie与 Session使用详解
2013/04/30 PHP
浅析php变量修饰符static的使用
2013/06/28 PHP
php中使用array_filter()函数过滤数组实例讲解
2021/03/03 PHP
javascript实现二分查找法实现代码
2007/11/12 Javascript
js实现iframe动态调整高度的代码
2008/01/06 Javascript
js从Cookies里面取值的简单实现
2014/06/30 Javascript
javascript自定义函数参数传递为字符串格式
2014/07/29 Javascript
浅谈js中StringBuffer类的实现方法及使用
2016/09/02 Javascript
Vuejs第十一篇组件之slot内容分发实例详解
2016/09/09 Javascript
初探JavaScript 面向对象(推荐)
2017/09/03 Javascript
KOA+egg.js集成kafka消息队列的示例
2018/11/09 Javascript
vue组件之间数据传递的方法实例分析
2019/02/12 Javascript
JavaScript实现星级评价效果
2019/05/17 Javascript
微信小程序 WXML节点信息查询详解
2019/07/29 Javascript
JQuery事件委托(适用于给动态生成的脚本元素添加事件)
2020/02/01 jQuery
webpack的 rquire.context用法实现工程自动化的方法
2020/02/07 Javascript
[04:11]DOTA2亚洲邀请赛小组赛第一日 TOP10精彩集锦
2015/01/30 DOTA
Python的Tornado框架实现图片上传及图片大小修改功能
2016/06/30 Python
5个很好的Python面试题问题答案及分析
2018/01/19 Python
Django添加sitemap的方法示例
2018/08/06 Python
python hook监听事件详解
2018/10/25 Python
Python实现定时执行任务的三种方式简单示例
2019/03/30 Python
基于Python和PyYAML读取yaml配置文件数据
2020/01/13 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
css3实现冲击波效果的示例代码
2018/01/11 HTML / CSS
Waterford加拿大官方网站:世界著名的水晶杯品牌
2016/11/01 全球购物
美国一家运动专业鞋类零售商:Warehouse Shoe Sale(WSS)
2018/03/28 全球购物
2013年军训通讯稿
2014/02/05 职场文书
高中军训感言200字
2014/02/23 职场文书
学生期末评语大全
2014/04/30 职场文书
高中教师个人总结
2015/02/10 职场文书
2015年高中班主任工作总结
2015/04/30 职场文书
2015年文明创建工作总结
2015/04/30 职场文书
如何用PHP实现分布算法之一致性哈希算法
2021/05/26 PHP