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 相关文章推荐
文本加密解密
Jun 23 Javascript
IE与Firefox在JavaScript上的7个不同句法分享
Oct 30 Javascript
利用js 进行输入框自动匹配字符的小例子
Jun 29 Javascript
js实现按钮控制图片360度翻转特效的方法
Feb 17 Javascript
基于css3新属性transform及原生js实现鼠标拖动3d立方体旋转
Jun 12 Javascript
JS限制条件补全问题实例分析
Dec 16 Javascript
Vue生命周期示例详解
Apr 12 Javascript
vue使用better-scroll实现下拉刷新、上拉加载
Nov 23 Javascript
JS实现的排列组合算法示例
Jul 16 Javascript
js实现一个简易计算器
Mar 30 Javascript
layer.alert自定义关闭回调事件的方法
Sep 27 Javascript
解决vue 使用setTimeout,离开当前路由setTimeout未销毁的问题
Jul 21 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
ThinkPHP之用户注册登录留言完整实例
2014/07/22 PHP
支持中文、字母、数字的PHP验证码
2015/05/04 PHP
PHP生成随机字符串实例代码(字母+数字)
2019/09/11 PHP
比较详细的javascript对象的property和prototype是什么一种关系
2007/08/06 Javascript
基于jQuery的ajax功能实现web service的json转化
2009/08/29 Javascript
ImageZoom 图片放大镜效果(多功能扩展篇)
2010/04/14 Javascript
javascript针对DOM的应用实例(一)
2012/04/15 Javascript
js输出阴历、阳历、年份、月份、周示例代码
2014/01/29 Javascript
函数式 JavaScript(一)简介
2014/07/07 Javascript
浅析node.js中close事件
2014/11/26 Javascript
JavaScript分秒倒计时器实现方法
2015/02/02 Javascript
javascript中 try catch用法
2015/08/16 Javascript
js实现无限级树形导航列表效果代码
2015/09/23 Javascript
解析Node.js基于模块和包的代码部署方式
2016/02/16 Javascript
星期几的不同脚本写法(推荐)
2016/06/01 Javascript
Express与NodeJs创建服务器的两种方法
2017/02/06 NodeJs
JS常见创建类的方法小结【工厂方式,构造器方式,原型方式,联合方式等】
2017/04/01 Javascript
基于vue.js 2.x的虚拟滚动条的示例代码
2018/01/23 Javascript
vue的diff算法知识点总结
2018/03/29 Javascript
JavaScript使用闭包模仿块级作用域操作示例
2019/01/21 Javascript
js JSON.stringify()基础详解
2019/06/19 Javascript
浅谈Vue.set实际上是什么
2019/10/17 Javascript
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
v-slot和slot、slot-scope之间相互替换实例
2020/09/04 Javascript
jQuery实现容器间的元素拖拽功能
2020/12/01 jQuery
教你用Python创建微信聊天机器人
2020/03/31 Python
Pytorch evaluation每次运行结果不同的解决
2020/01/02 Python
使用CSS3代码绘制可爱的Hello Kitty猫
2016/08/03 HTML / CSS
如何在Canvas上的图形/图像绑定事件监听的实现
2020/09/16 HTML / CSS
凌阳科技股份有限公司C++程序员面试题笔试题
2014/11/20 面试题
工商管理专业实习大学生自我鉴定
2013/09/19 职场文书
班长岗位职责
2013/11/10 职场文书
村当支部个人对照检查材料思想汇报
2014/10/06 职场文书
质检员岗位职责
2015/02/03 职场文书
给校长的建议书作文400字
2015/09/14 职场文书
win10系统计算机图标怎么调出来?win10调出计算机图标的方法
2022/08/14 数码科技