本文介紹了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
總結
步驟五
初始化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){....}以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
| 
 
 | 
新聞熱點
疑難解答