Angularjs的启动过程分析


Posted in Javascript onJuly 18, 2017

本文介绍了Angularjs的启动过程分析,分享给大家

启动过程(v1.3.9)

步骤一

用自执行函数的形式让整个代码在加载完成之后立即执行

in angular.js Line6

(function(window, document, undefined)

在window上暴露一个唯一的全局对象angular,Line250 

angular = window.angular || (window.angular = {})

 获得其它工具模块 Line 2129

function publishExternalAPI(angular) {
  extend(angular, {
   'bootstrap': bootstrap,
   'copy': copy,
   'extend': extend,
   'equals': equals,
   'element': jqLite,
   'forEach': forEach,
   'injector': createInjector,
   'noop': noop,
   'bind': bind,
   .....

我们来看看angular全局对象都有什么东西

Angularjs的启动过程分析

接着,我们使用全局对象中的isFunction 来遍历一下angular全局对象上的属性,函数

var counter = 0;
 for (var p in angular) {
   counter++;
   if (angular.isFunction(angular[p])) {
     console.log("function->" + p);
   } else {
     console.log("property-->" + p + "-->" + angular[p]);
   }
 }
 console.log(counter);

有两个property,其它都是function

Angularjs的启动过程分析

我们再来看看injector里都有什么

/**
  * angular.injector();
  */
 var injector = angular.injector();
 console.log(injector);

一共有5个方法

annotate:分析函数签名(不要new的原因)

Angularjs的启动过程分析

步骤二

检查是不是多次导入Angular:window.angular.bootstrap(通过检查指定的元素上是否已经存在injector进行判断)

in angular.js line 26041

if (window.angular.bootstrap) {
    //AngularJS is already loaded, so we can return here...
    console.log('WARNING: Tried to load angular more than once.');
    return;
   }

angular的三种启动方式

自动启动

Angular会自动的找到ng-app,将它作为启动点,自动启动

<!DOCTYPE html>
 <html ng-app="myModule">

 <head>
   <title>New Page</title>
   <meta charset="utf-8" />
   <script type="text/javascript" src="../../vendor/bower_components/angular/angular.min.js"></script>
   <script type="text/javascript" src="./02.boot1.js"></script>
 </head>

 <body>
   <div ng-controller="MyCtrl">
     <span>{{Name}}</span>
   </div>
 </body>
 </html>

js

var myModule = angular.module("myModule", []);
 myModule.controller('MyCtrl', ['$scope',
   function($scope) {
     $scope.Name = "Puppet";
   }
 ]);

手动启动

在没有ng-app的情况下,只需要在js中添加一段注册代码即可

<body>
   <div ng-controller="MyCtrl">
     <span>{{Name}}</span>
   </div>
 </body>

js

var myModule = angular.module("myModule", []);
 myModule.controller('MyCtrl', ['$scope',
   function($scope) {
     $scope.Name = "Puppet";
   }
 ]);

 /**
  * 这里要用ready函数等待文档初始化完成
  */
 angular.element(document).ready(function() {
   angular.bootstrap(document, ['myModule']);
 });

多个ng-app

ng中,angular的ng-app是无法嵌套使用的,在不嵌套的情况下有多个ng-app,他默认只会启动第一个ng-app,第二个第三个需要手动启动(注意,不要手动启动第一个,虽然可以运行,但会抛异常)

<body>
   <div id="app1" ng-app="myModule1">
     <div ng-controller="MyCtrl">
       <span>{{Name}}</span>
     </div>
   </div>
   <div id="app2" ng-app="myModule2">
     <div ng-controller="MyCtrl">
       <span>{{Name}}</span>
     </div>
   </div>
 </body>

js

/**
  * 第一个APP
  * @type {[type]}
  */
 var myModule1 = angular.module("myModule1", []);
 myModule1.controller('MyCtrl', ['$scope',
   function($scope) {
     $scope.Name = "Puppet";
   }
 ]);
 // angular.element(document).ready(function() {
 //   angular.bootstrap(app1, ['MyModule1']);
 // });

 /**
  * 第二个APP
  * @type {[type]}
  */
 var myModule2 = angular.module("myModule2", []);
 myModule2.controller('MyCtrl', ['$scope',
   function($scope) {
     $scope.Name = "Vincent";
   }
 ]);
 angular.element(document).ready(function() {
   angular.bootstrap(app2, ['myModule2']);
 });

步骤三

尝试绑定jQuery,如果发现导入了jQuery ,则使用导入的jQuery,否则,使用Angular自己封装的JQLite

in angular.js line 1521:

bindJQuery();

in angular.js line 1534:

jQuery = window.jQuery;

if (jQuery && jQuery.fn.on) {
  jqLite = jQuery;
  extend(jQuery.fn, {
   scope: JQLitePrototype.scope,
   isolateScope: JQLitePrototype.isolateScope,
   controller: JQLitePrototype.controller,
   injector: JQLitePrototype.injector,
   inheritedData: JQLitePrototype.inheritedData
  });

测试

<html ng-app="myModule">


<body>
  <div>
    <div ng-controller="MyCtrl">
      <span>{{Name}}</span>
    </div>
  </div>
</body>

</html>

js

var myModule = angular.module("myModule", []);
myModule.controller('MyCtrl', ['$scope',
  function($scope) {
    $scope.Name = "Puppet";
  }
]);

查看执行流程

Angularjs的启动过程分析

步骤四

发布ng提供的API

in angular.js line 2162 : publishExternalAPI(angular);

//构建模块加载器
angularModule = setupModuleLoader(window);
 try {
  angularModule('ngLocale');
 } catch (e) {
  angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
 }

模块加载器的实现原理

in angular.js function setupModuleLoader(window)

function setupModuleLoader(window) {

 var $injectorMinErr = minErr('$injector');
 var ngMinErr = minErr('ng');

 function ensure(obj, name, factory){
 return obj[name] || (obj[name] = factory());
 }
 var angular = ensure(window, 'angular', Object);
 // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
 angular.$$minErr= angular.$ $minErr || minErr;
 //把module方法放到angular的全局对象上,ensure就是一个属性拷贝的过程
return ensure(angular, 'module', function(){
  //模块缓存
  var modules = {};
}

把工具函数给载到模块里

return function module(name, requires, configFn) {
......
}

查看模块里所包含的内容

<!DOCTYPE html>
<html ng-app="myModule">

</html>

JS

/**
 * 定义模块
 */
var myModule = angular.module("myModule", []);

/**
 * 从debug的过程可以看到,angular中的“模块”只是一个闭包空间(或者叫命名空间)
 * 所有模块都被注册在modules这个对象上
 */
console.log(myModule);

查看控制台

Angularjs的启动过程分析

构建内置模块ng

in angular.js line 2169 publishExternalAPI(angular)

angularModule('ng', ['ngLocale'], ['$provide',
  function ngModule($provide) {
   // $ $sanitizeUriProvider needs to be before $compileProvider as it is used by it.
   $provide.provider({
    $ $sanitizeUri: $$SanitizeUriProvider
   });
   $provide.provider('$compile', $CompileProvider).
    directive({
      a: htmlAnchorDirective,
      input: inputDirective,
      ......

加载了所有内置的directive,provider.注册ng内核Provider:两个最重要的$parser $rootScope

总结

  1. 工具函数拷贝到angular全局对象上;
  2. 调用setupModuleLoader方法创建模块定义和加载工具(挂在全局对象window.angular上);
  3. 构建内置模块ng;
  4. 创建ng内置的directive和provider;
  5. 两个重要的provider:$parse 和 $rootScope;

步骤五

初始化Angular - 查找Ng-app

jqLite(document).ready(function() {
  angularInit(document, bootstrap);
 });

bootstrap

创建injector,拉起内核和启动模块,调用compile服务(一个ng-app只有一个injector)

in angular.js line 1415

function bootstrap(element, modules, config){
....
}

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

Javascript 相关文章推荐
js根据给定的日期计算当月有多少天实现思路及代码
Feb 25 Javascript
Javascript执行效率全面总结
Nov 04 Javascript
javascript中数组array及string的方法总结
Nov 28 Javascript
js中的事件捕捉模型与冒泡模型实例分析
Jan 10 Javascript
js字符串操作方法实例分析
May 06 Javascript
vueJS简单的点击显示与隐藏的效果【实现代码】
May 03 Javascript
javascript DOM的详解及实例代码
Mar 06 Javascript
Bootstrap面板(Panels)的简单实现代码
Mar 17 Javascript
jQuery、layer实现弹出层的打开、关闭功能
Jun 28 jQuery
JS+jQuery实现注册信息的验证功能
Sep 26 jQuery
详解小程序不同页面之间通讯的解决方案
Nov 23 Javascript
使用JS location实现搜索框历史记录功能
Dec 23 Javascript
关于javascript sort()排序你可能忽略的一点理解
Jul 18 #Javascript
jQuery扇形定时器插件pietimer使用方法详解
Jul 18 #jQuery
ES6中的rest参数与扩展运算符详解
Jul 18 #Javascript
ES6学习之变量的两种命名方法示例
Jul 18 #Javascript
vue实现表格增删改查效果的实例代码
Jul 18 #Javascript
js canvas实现适用于移动端的百分比仪表盘dashboard
Jul 18 #Javascript
vue深入解析之render function code详解
Jul 18 #Javascript
You might like
php和js交互一例-PHP教程,PHP应用
2007/01/03 PHP
php实现微信公众平台账号自定义菜单类
2015/10/11 PHP
PHP接口并发测试的方法(推荐)
2016/12/15 PHP
form表单传递数组数据、php脚本接收的实例
2017/02/09 PHP
PHP简单实现遍历目录下特定文件的方法小结
2017/05/22 PHP
使用自定义setTimeout和setInterval使之可以传递参数和对象参数
2009/04/24 Javascript
js监控IE火狐浏览器关闭、刷新、回退、前进事件
2014/07/23 Javascript
浅谈javascript对象模型和function对象
2014/12/26 Javascript
jQuery学习笔记之jQuery中的$
2015/01/19 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
2017/06/13 jQuery
基于jQuery Ajax实现下拉框无刷新联动
2017/12/06 jQuery
原生JS实现手动轮播图效果实例代码
2018/11/22 Javascript
layui富文本编辑器前端无法取值的解决方法
2019/09/18 Javascript
vue动态设置路由权限的主要思路
2021/01/13 Vue.js
[03:42]2016国际邀请赛中国区预选赛首日现场玩家采访
2016/06/26 DOTA
Python中装饰器兼容加括号和不加括号的写法详解
2017/07/05 Python
Python+selenium实现截图图片并保存截取的图片
2018/01/05 Python
Python进度条实时显示处理进度的示例代码
2018/01/30 Python
树莓派与PC端在局域网内运用python实现即时通讯
2019/06/22 Python
Python二进制文件读取并转换为浮点数详解
2019/06/25 Python
使用Python实现图像标记点的坐标输出功能
2019/08/14 Python
numpy求平均值的维度设定的例子
2019/08/24 Python
Python脚本操作Excel实现批量替换功能
2019/11/20 Python
python与mysql数据库交互的实现
2020/01/06 Python
django 文件上传功能的相关实例代码(简单易懂)
2020/01/22 Python
Python基础之字符串操作常用函数集合
2020/02/09 Python
解决运行出现'dict' object has no attribute 'has_key'问题
2020/07/15 Python
Python基于callable函数检测对象是否可被调用
2020/10/16 Python
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的
2015/07/24 面试题
最新创业融资计划书
2014/01/19 职场文书
党校学习心得体会范文
2014/09/09 职场文书
我的职业生涯规划:打造自己的运动帝国
2014/09/18 职场文书
保护动物的宣传语
2015/07/13 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
Mysql systemctl start mysqld报错的问题解决
2021/06/03 MySQL
教你怎么用Python selenium操作浏览器对象的基础API
2021/06/23 Python