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全局对象都有什么东西

  • 接着,我们使用全局对象中的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

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

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

一共有5个方法
annotate:分析函数签名(不要new的原因)


步骤二
  • 检查是不是多次导入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";
    }
]);

查看执行流程

步骤四

发布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);

查看控制台

构建内置模块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){
....
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容