欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Angularjs的启动过程分析

程序员文章站 2022-04-29 08:01:08
本文介绍了angularjs的启动过程分析,分享给大家 启动过程(v1.3.9) 步骤一 用自执行函数的形式让整个代码在加载完成之后立即执行 in angu...

本文介绍了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){
....
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。