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 相关文章推荐
网页加载时页面显示进度条加载完成之后显示网页内容
Dec 23 Javascript
jQuery学习笔记之jQuery中的$
Jan 19 Javascript
DOM基础教程之事件类型
Jan 20 Javascript
jQuery实现动态添加和删除一个div
Aug 12 Javascript
在JavaScript中对HTML进行反转义详解
May 18 Javascript
jQuery实现的省市县三级联动菜单效果完整实例
Aug 01 Javascript
jQuery Easyui快速入门教程
Aug 21 Javascript
jquery select2的使用心得(推荐)
Dec 04 Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
Dec 20 jQuery
vue-cli与webpack处理静态资源的方法及webpack打包的坑
May 15 Javascript
vue实现todolist基本功能以及数据存储功能实例详解
Apr 11 Javascript
jQuery实现数字华容道小游戏(实例代码)
Jan 16 jQuery
关于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
BBS(php &amp; mysql)完整版(五)
2006/10/09 PHP
Look And Say 序列php实现代码
2011/05/22 PHP
php实现按指定大小等比缩放生成上传图片缩略图的方法
2014/12/15 PHP
PHP lcfirst()函数定义与用法
2019/03/08 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
2020/03/27 PHP
extjs grid设置某列背景颜色和字体颜色的方法
2010/09/03 Javascript
JS焦点图切换,上下翻转
2011/05/12 Javascript
js实现div模拟模态对话框展现URL内容
2016/05/27 Javascript
使用BootStrap进行轮播图的制作
2017/01/06 Javascript
JavaScript基本类型值-Number类型
2017/02/24 Javascript
jQuery 中msgTips 顶部弹窗效果实现代码
2017/08/14 jQuery
理解Koa2中的async&amp;await的用法
2018/02/05 Javascript
微信小程序使用swiper组件实现类3D轮播图
2018/08/29 Javascript
解决vue keep-alive 数据更新的问题
2018/09/21 Javascript
JavaScript字符串处理常见操作方法小结
2019/11/15 Javascript
Angular 多模块项目构建过程
2020/02/13 Javascript
vue-resource post数据时碰到Django csrf问题的解决
2020/03/13 Javascript
vue 数据双向绑定的实现方法
2021/03/04 Vue.js
[02:00]最后,我终于出了辉耀
2018/03/27 DOTA
详解duck typing鸭子类型程序设计与Python的实现示例
2016/06/03 Python
关于Python 3中print函数的换行详解
2017/08/08 Python
Python实现定期检查源目录与备份目录的差异并进行备份功能示例
2019/02/27 Python
python三方库之requests的快速上手
2019/03/04 Python
Python 一键制作微信好友图片墙的方法
2019/05/16 Python
Python自动抢红包教程详解
2019/06/11 Python
Python实现Mysql数据统计及numpy统计函数
2019/07/15 Python
Python实现AI换脸功能
2020/04/10 Python
python3.6中anaconda安装sklearn踩坑实录
2020/07/28 Python
如何将无状态会话Bean发布为WEB服务,只有无状态会话Bean可以发布为WEB服务?
2015/12/03 面试题
宗教学大学生职业生涯规划范文
2014/02/08 职场文书
小区推广策划方案
2014/06/06 职场文书
抗震救灾标语
2014/06/26 职场文书
就业证明函
2015/06/17 职场文书
八一建军节主持词
2015/07/01 职场文书
开业典礼致辞
2015/07/29 职场文书
一次MySQL启动导致的事故实战记录
2021/09/15 MySQL