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实现的真正的iframe高度自适应(兼容IE,FF,Opera)
Mar 07 Javascript
javascript特殊用法示例介绍
Nov 29 Javascript
jquery五角星评分插件示例分享
Feb 21 Javascript
jQuery 选择器(61种)整理总结
Sep 26 Javascript
jquery获取input type=text中的值的各种方式(总结)
Dec 02 Javascript
微信小程序 合法域名校验出错详解及解决办法
Mar 09 Javascript
Js利用Canvas实现图片压缩功能
Sep 13 Javascript
JavaScript中import用法总结
Jan 20 Javascript
微信小程序设置全局请求URL及封装wx.request请求操作示例
Apr 02 Javascript
微信小程序位置授权处理方法
Jun 13 Javascript
微信小程序数据统计和错误统计的实现方法
Jun 26 Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
Mar 03 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无限分类代码,支持数组格式化、直接输出菜单两种方式
2011/05/18 PHP
20个PHP常用类库小结
2011/09/11 PHP
php从给定url获取文件扩展名的方法
2015/03/14 PHP
PHP仿tp实现mvc框架基本设计思路与实现方法分析
2018/05/23 PHP
thinkPHP框架通过Redis实现增删改查操作的方法详解
2019/05/13 PHP
laravel 之 Eloquent 模型修改器和序列化示例
2019/10/17 PHP
使一个函数作为另外一个函数的参数来运行的javascript代码
2007/08/13 Javascript
dojo学习第二天 ajax异步请求之绑定列表
2011/08/29 Javascript
JavaScript 学习笔记之数据类型
2015/01/14 Javascript
javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2015/04/01 Javascript
javascript鼠标滑过显示二级菜单特效
2020/11/18 Javascript
浅谈js算法和流程控制
2016/12/29 Javascript
Bootstrap轮播图学习使用
2017/02/10 Javascript
ionic2打包android时gradle无法下载的解决方法
2017/04/05 Javascript
详解微信小程序支付流程与梳理
2019/07/16 Javascript
在layui框架中select下拉框监听更改事件的例子
2019/09/20 Javascript
浅探express路由和中间件的实现
2019/09/30 Javascript
layui实现数据表格隐藏列的示例
2019/10/25 Javascript
js实现超级玛丽小游戏
2020/03/18 Javascript
Python进行数据科学工作的简单入门教程
2015/04/01 Python
在Python中定义和使用抽象类的方法
2016/06/30 Python
Python爬取附近餐馆信息代码示例
2017/12/09 Python
Sublime开发python程序的示例代码
2018/01/24 Python
python lxml中etree的简单应用
2019/05/10 Python
Python交互式图形编程的实现
2019/07/25 Python
Python requests模块cookie实例解析
2020/04/14 Python
Myprotein瑞典官方网站:畅销欧洲英国运动营养品牌
2018/01/22 全球购物
Skyscanner新西兰:全球领先的旅游搜索网站
2019/08/26 全球购物
Unix如何添加新的用户
2014/08/20 面试题
会计专业自我鉴定
2014/02/10 职场文书
十八届三中全会报告学习材料
2014/02/17 职场文书
《颐和园》教学反思
2014/02/26 职场文书
如何写一份好的英文求职信
2014/03/19 职场文书
对外汉语专业大学生职业生涯规划范文
2014/09/13 职场文书
学生会辞职信
2015/03/02 职场文书
2016创先争优活动党员公开承诺书
2016/03/24 职场文书