一、浏览器下载HTML/CSS/JavaScript等

  当你转到一个页面地址后,浏览器先回下载这个HTML,同时,会开启一些辅助线程下载所关联的script标签和link标签里引用的文件。

二、浏览器构建DOM树

  下载的同时浏览器会开始构建DOM树,内嵌或引入的脚本也会开始执行,也就是说浏览器会逐个加载DOM树中的每一个元素节点,可以把AngularJS当做一个类似jQuery的js库,通过<script>标签引入到HTML中,此时Angular被作为一个普通的DOM节点等待浏览器解析,当浏览器解析到这个节点时,发现它是一个js文件,那么浏览器会停止解析剩余的DOM节点,开始执行这个js(即angular.js)。

三、jQuery初始化

  引用脚本中有一个是jQuery(如其不在AngularJS脚本之前引用,AngularJS就会启动其内置的jQLite),其启动代码会给自己挂接上document对象的DOMContentLoaded事件,通过调用jQuery.ready(callback)把一个回调函数注册到该事件中,后边DOM构建完毕时候,会触发该事件,并执行回调函数,会开始启动Angular,在触发之前,还有许多脚本要初始化,也就是DOM还未解析完成。

四、AngularJS初始化

  需要初始化的脚本中有另外一些AngularJS模块及其子模块,或一些第三方模块,此时会按引用顺序开始它们的初始化过程。模块的初始化过程大致相同:

  1、按名字创建模块,是一个对象,是其他Angular对象的注册表。

  2、在这个模块中注册各种Angular对象,如Controller、Service、Directive等,形成一个有名字和回调函数组成的对照表,这些回调函数现在还不会执行。

  3、模块中注册“config回调函数”和"run回调函数",分别在模块开始加载和加载结束时候执行,现在只是注册,不会执行。

五、jQuery启动

  当页面及其直接饮用的js文件都下载执行完后,DOM构建完成,浏览器会触发document对象的DOMContentLoaded事件,在jQuery.ready中注册的回调函数也会调用,其中代码会开启动AngularJS。

六、AngularJS启动

  此时,AngularJS正式登场,第一件事就是查找一个带有ng-app指令的节点,通常出现在body或html元素中,也可以出现在任意节点上,而且,一个页面可以有多个这样的节点;AngularJS找到第一个带有 ng-app节点,并调用angular.bootstrap(element,moduleName),element就是该节点,moduleName是该节点上指定的模块。

  AngularJS自启动方式,只会启动第一个ng-app的module;对于多个ng-app启动的方式,必须采用手动angular.bootstrap来启动。

  推荐,仅适用一个ng-app,然后,用Module和Controller来划分页面。

七、加载子模块

  AngularJS首先会创建一个注入器(injector),并关联到所在节点上,前边模块注册的一大堆Angular对象,都需要它才能被其他代码调用;接着,对当前节点的模块和所依赖模块进行初始化,顺序执行所有的"config回调函数";

  在config回调函数中能够使用的只有注册的常量(Constant)对象和Provider类,这里也是程序中唯一可以直接访问Provider类对服务进行配置的地方。

  比如,路由服务的Provider就是在这里初始化,但是,只是负责记录一个URL到“模板/控制器”组的映射表,供后边使用。

八、启动子模块

  模块加载完成后,会执行所有“run回调函数”,在这个阶段,各种Angular对象都可以使用了(如果想使用),包括各种Service、Factory等。

  接下来,控制权会转到路由模块,使用$location服务解析当前页面的URL,然后,根据这个URL查找响应的“模板/控制器”对(七、中生成的),来渲染一个页面。

九、渲染页面

  路由模块会先创建一个Scope对象,并加载模板,加载完毕后把它的内容传给$complie对象,其会先把它解析成一个静态DOM树,然后逐个扫描这棵DOM树种的指令,通过这些指令把Scope对象DOM树关联起来,包括渲染内容的函数和进行事件处理的函数。最后,用它替换一个特定指令所在的节点,即,ng-view/ui-view。

  $compile服务通过遍历DOM树的方式查找有声明指令的DOM元素。当碰到带有一个或多个指令的DOM元素时,它会排序这些指令(基于指令的priority优先级),然后使用$injector服务查找和收集指令的compile函数并执行它。每个节点的编译方法运行之后,$compile服务就会调用链接函数。

十、数据绑定和摘要循环

  此时,页面已经显示出来,但是数据还没有被渲染,AngularJS会自动使用Scope中的数据渲染一遍。

  通过”脏检查机制”,使得用户修改了数据,也能被渲染出来。

  它是一个称为“摘要循环”的过程,AngularJS会给每一个Scope成员变量求出一个 摘要值(能唯一标识一个变量),并保存在一个变量中,当调用Scope的$digest/$apply方法时候,会重新计算一遍摘要值,只要数据变化了,就会更新界面。

也就是说,Angular提供了自己的事件循环。指令自身会注册事件监听器,因此当事件被触发时,指令函数就会运行在AngularJS的$digest循环中。$digest循环会等待$watch表达式列表,当检测到模型变化后,就会调用$watch函数,然后再次查看$watch列表以确保没有

模型被改变。一旦摘要循环稳定下来,并且检测到没有潜在的变化了,执行过程就会离开Angular上下文并且会回到浏览器中,DOM将会被渲染到这里。

  注意:$digest不用直接调用,$apply是对它的封装,其也一般很少调用,因为在一些AngularJS事件指令以及$timeout等服务中,会自动调用它来确保界面刷新。

       自己挂接第三方组件的事件,就得记得手动调用一次$apply。

  到此,一个典型的AngularJS程序就启动成功了。

AngularJS 启动执行过程的更多相关文章

  1. 浅谈AngularJS启动引导过程

    我们都知道AngularJS默认会执行app.js来启动整个angular项目,但你知道angular具体执行过程吗? 一.自动引导启动框架 例如我们有如下代码,我们想要完成一个指令功能: <h ...

  2. 第8章7节《MonkeyRunner源代码剖析》MonkeyRunner启动执行过程-小结

    最后我们对MonkeyRunner启动的过程做一个总结,当然,当中也包括启动Monkey,尽管它不属于启动过程的一部分: monkeyrunner这个shell脚本会先设置一些执行环境的系统属性保存到 ...

  3. 第8章4节《MonkeyRunner源代码剖析》MonkeyRunner启动执行过程-启动AndroidDebugBridge

    上一节我们看到在启动AndroidDebugBridge的过程中会调用其start方法,而该方法会做2个基本的事情: 715行startAdb:开启AndroidDebugBridge 722-723 ...

  4. 第8章2节《MonkeyRunner源代码剖析》MonkeyRunner启动执行过程-解析处理命令行參数

    MonkeyRunnerStarter是MonkeyRunner启动时的入口类,由于它里面包括了main方法.它的整个启动过程主要做了以下几件事情: 解析用户启动MonkeyRunner时从命令行传输 ...

  5. 第8章5节《MonkeyRunner源代码剖析》MonkeyRunner启动执行过程-执行測试脚本

    MonkeyRunner在准备好AndroidDebugBridge和DeviceMonitor等服务之后,就基本上是攻克了和目标设备通信的问题了,那往下须要做的就是把測试脚本执行起来了. 178 p ...

  6. AngularJS应用的启动和执行过程

    启动(startup): <!doctype html> <html ng-app> <head> <script src="http://code ...

  7. AngularJS的启动引导过程

    原文:http://www.angularjs.cn/A137?utm_source=ourjs.com 目录: 引导之前 自动引导启动框架 手工引导启动框架 引导第1步:创建注入器 引导第2步:创建 ...

  8. AngularJS的加载执行过程

    1. HTML页面的加载,这会触发加载页面包含的所有JS (包括 AngularJS) 2. AngularJS启动,搜寻所有的指令(directive) 3. 找到ng-app,搜寻其指定的模块(M ...

  9. Angularjs启动入口, splash画面,与加快启动的技巧

    Angularjs启动入口, splash画面,与加快启动的技巧 Angularjs启动入口 * 自动响应DOMContentLoaded event * 从ngApp指定的入口启动: 在angula ...

随机推荐

  1. 放大Button热区的方法哟

    //添加图片不能用backgroundimage [btn setImage:image5 forState:]; //然后 btn.imageEdgeInsets = UIEdgeInsetsMak ...

  2. PID参数调节口诀

    参数整定找最佳, 从小到大顺序查. 先是比例后积分, 最后再把微分加. 曲线振荡很频繁, 比例度盘要放大. 曲线漂浮绕大弯, 比例度盘往小扳. 曲线偏离回复慢, 积分时间往下降. 曲线波动周期长, 积 ...

  3. 谁说delphi没有IOCP库,delphi新的IOCP类库,开源中: DIOCP组件JSON流模块说明

    单元:JSonStream.pas 简介:本单元实现 流和json对象的相互转换,其中有一些保留的key. 依赖:superobject 保留key: __result.errCode  返回的错误编 ...

  4. 去掉tableView空白区域的分割线

    //把多余的分割线去掉 UIView * footerView = [[UIView alloc] initWithFrame:CGRectZero]; self.tableView.tableFoo ...

  5. QueryRunner类的八种结果处理集

    package cn.jy.demo; import java.sql.Connection; import java.sql.SQLException; import java.util.List; ...

  6. socket.io的connect连接时不断的进行自动连接,并产生错误net::ERR_EMPTY_RESPONSE

    socket = io.connect('http://192.168.1.200:9043?uuid=333'); 执行上面的语句时,产生下面的错误: 后来经过排查,是由于项目的jdk版本过低引起的 ...

  7. centos6.5虚拟机每次都要ifup eth0的解决办法

    修改文件/etc/sysconfig/network-scripts/ifcfg-eth0把ONBOOT=no改ONBOOT=yes

  8. 使用Apache CXF和Spring集成创建Web Service(zz)

    使用Apache CXF和Spring集成创建Web Service 您的评价:       还行  收藏该经验       1.创建HelloWorld 接口类 查看源码 打印? 1 package ...

  9. matlab柱面图

    f=@(x,y)log(y);  % ln(x)函数,平行于x轴ezsurf(f,[-pi*2,pi*2,0,20])

  10. C++STL queue

    queue队列 先进先出 queue<int> q1; q1.push();//插入元素 q1.front();//求队头元素 q1.pop();//删除队头元素 q1.empty();/ ...