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工具 Cookie 封装
Aug 21 Javascript
Javascript实现的常用算法(如冒泡、快速、鸽巢、奇偶等)
Apr 29 Javascript
javascript委托(Delegate)blur和focus用法实例分析
May 26 Javascript
js实现input框文字动态变换显示效果
Aug 19 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
May 10 Javascript
JavaScript生成带有缩进的表格代码
Jun 15 Javascript
Vue.js每天必学之指令系统与自定义指令
Sep 07 Javascript
WEB 前端开发中防治重复提交的实现方法
Oct 26 Javascript
浅谈如何使用 webpack 优化资源
Oct 20 Javascript
vue使用高德地图根据坐标定位点的实现代码
Aug 22 Javascript
微信小程序图片自适应实现解析
Jan 21 Javascript
TypeScript魔法堂之枚举的超实用手册
Oct 29 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/01/12 PHP
php curl常见错误:SSL错误、bool(false)
2011/12/28 PHP
php如何调用webservice应用介绍
2012/11/24 PHP
Windows下Apache + PHP SESSION丢失的解决过程全纪录
2015/04/07 PHP
php实现微信公众平台发红包功能
2018/06/14 PHP
为Plesk PHP7启用Oracle OCI8扩展方法总结
2019/03/29 PHP
PHP接入微信H5支付的方法示例
2019/10/28 PHP
使用JQuery进行跨域请求
2010/01/25 Javascript
再谈querySelector和querySelectorAll的区别与联系
2012/04/20 Javascript
javascript学习(二)javascript常见问题总结
2013/01/02 Javascript
js 图片随机不定向浮动的实现代码
2013/07/02 Javascript
JS简单实现动画弹出层效果
2015/05/05 Javascript
简介EasyUI datagrid editor combogrid搜索框的实现
2016/04/01 Javascript
详谈jQuery中使用attr(), prop(), val()获取value的异同
2017/04/25 jQuery
jQuery实现的form转json经典示例
2017/10/10 jQuery
jq源码解析之绑在$,jQuery上面的方法(实例讲解)
2017/10/13 jQuery
基于BootStrap的文本编辑器组件Summernote
2017/10/27 Javascript
jquery实现企业定位式导航效果
2018/01/01 jQuery
微信小程序之多文件下载的简单封装示例
2018/01/29 Javascript
AngularJs的UI组件ui-Bootstrap之Tooltip和Popover
2018/07/13 Javascript
webpack 3.X学习之多页面打包的方法
2018/09/04 Javascript
Layui Form 自定义验证的实例代码
2019/09/14 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
JQuery样式与属性设置方法分析
2019/12/07 jQuery
详解阿里Node.js技术文档之process模块学习指南
2021/01/04 Javascript
Vue中的nextTick作用和几个简单的使用场景
2021/01/25 Vue.js
python读取html中指定元素生成excle文件示例
2014/04/03 Python
Python中请使用isinstance()判断变量类型
2014/08/25 Python
Python3.5 + sklearn利用SVM自动识别字母验证码方法示例
2019/05/10 Python
三个儿子教学反思
2014/02/03 职场文书
美容院营销方案
2014/03/05 职场文书
学习优秀党务工作者先进事迹材料思想报告
2014/09/17 职场文书
离婚起诉书范文2016
2015/11/26 职场文书
经典励志格言:每日一句,让你每天充满能量
2019/08/16 职场文书
Java中常用解析工具jackson及fastjson的使用
2021/06/28 Java/Android
postgresql如何找到表中重复数据的行并删除
2023/05/08 MySQL