Angularjs的啟動(dòng)過(guò)程分析
本文介紹了Angularjs的啟動(dòng)過(guò)程分析,分享給大家
啟動(dòng)過(guò)程(v1.3.9)
步驟一
用自執(zhí)行函數(shù)的形式讓整個(gè)代碼在加載完成之后立即執(zhí)行
in angular.js
Line6
(function(window, document, undefined)
在window上暴露一個(gè)唯一的全局對(duì)象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, .....
我們來(lái)看看angular全局對(duì)象都有什么東西
接著,我們使用全局對(duì)象中的isFunction 來(lái)遍歷一下angular全局對(duì)象上的屬性,函數(shù)
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);
有兩個(gè)property,其它都是function
我們?cè)賮?lái)看看injector里都有什么
/** * angular.injector(); */ var injector = angular.injector(); console.log(injector);
一共有5個(gè)方法
annotate:分析函數(shù)簽名(不要new的原因)
步驟二
檢查是不是多次導(dǎo)入Angular:window.angular.bootstrap(通過(guò)檢查指定的元素上是否已經(jīng)存在injector進(jìn)行判斷)
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的三種啟動(dòng)方式
自動(dòng)啟動(dòng)
Angular會(huì)自動(dòng)的找到ng-app,將它作為啟動(dòng)點(diǎn),自動(dòng)啟動(dòng)
<!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"; } ]);
手動(dòng)啟動(dòng)
在沒有ng-app的情況下,只需要在js中添加一段注冊(cè)代碼即可
<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函數(shù)等待文檔初始化完成 */ angular.element(document).ready(function() { angular.bootstrap(document, ['myModule']); });
多個(gè)ng-app
ng中,angular的ng-app是無(wú)法嵌套使用的,在不嵌套的情況下有多個(gè)ng-app,他默認(rèn)只會(huì)啟動(dòng)第一個(gè)ng-app,第二個(gè)第三個(gè)需要手動(dòng)啟動(dòng)(注意,不要手動(dòng)啟動(dòng)第一個(gè),雖然可以運(yùn)行,但會(huì)拋異常)
<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
/** * 第一個(gè)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']); // }); /** * 第二個(gè)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,如果發(fā)現(xiàn)導(dǎo)入了jQuery ,則使用導(dǎo)入的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 });
測(cè)試
<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"; } ]);
查看執(zhí)行流程
步驟四
發(fā)布ng提供的API
in angular.js
line 2162 : publishExternalAPI(angular);
//構(gòu)建模塊加載器 angularModule = setupModuleLoader(window); try { angularModule('ngLocale'); } catch (e) { angularModule('ngLocale', []).provider('$locale', $LocaleProvider); }
模塊加載器的實(shí)現(xiàn)原理
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的全局對(duì)象上,ensure就是一個(gè)屬性拷貝的過(guò)程 return ensure(angular, 'module', function(){ //模塊緩存 var modules = {}; }
把工具函數(shù)給載到模塊里
return function module(name, requires, configFn) { ...... }
查看模塊里所包含的內(nèi)容
<!DOCTYPE html> <html ng-app="myModule"> </html>
JS
/** * 定義模塊 */ var myModule = angular.module("myModule", []); /** * 從debug的過(guò)程可以看到,angular中的“模塊”只是一個(gè)閉包空間(或者叫命名空間) * 所有模塊都被注冊(cè)在modules這個(gè)對(duì)象上 */ console.log(myModule);
查看控制臺(tái)
構(gòu)建內(nèi)置模塊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, ......
加載了所有內(nèi)置的directive,provider.注冊(cè)ng內(nèi)核Provider:兩個(gè)最重要的$parser
和 $rootScope
總結(jié)
- 工具函數(shù)拷貝到angular全局對(duì)象上;
- 調(diào)用setupModuleLoader方法創(chuàng)建模塊定義和加載工具(掛在全局對(duì)象window.angular上);
- 構(gòu)建內(nèi)置模塊ng;
- 創(chuàng)建ng內(nèi)置的directive和provider;
- 兩個(gè)重要的provider:$parse 和 $rootScope;
步驟五
初始化Angular - 查找Ng-app
jqLite(document).ready(function() { angularInit(document, bootstrap); });
bootstrap
創(chuàng)建injector,拉起內(nèi)核和啟動(dòng)模塊,調(diào)用compile服務(wù)(一個(gè)ng-app只有一個(gè)injector)
in angular.js
line 1415
function bootstrap(element, modules, config){ .... }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用Jasmine對(duì)Angular進(jìn)行單元測(cè)試的方法詳解
單元測(cè)試是一種能夠幫助開發(fā)者驗(yàn)證代碼中某一部分有效性的技術(shù)。下面這篇文章主要給大家介紹了關(guān)于利用Jasmine對(duì)Angular進(jìn)行單元測(cè)試的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-06-06什么是 AngularJS?AngularJS簡(jiǎn)介
這篇文章主要介紹了什么是 AngularJS?AngularJS簡(jiǎn)介,本文講解了AngularJS方方面面的基礎(chǔ)知識(shí),AngularJS 是一個(gè)為動(dòng)態(tài)WEB應(yīng)用設(shè)計(jì)的結(jié)構(gòu)框架。它能讓你使用HTML作為模板語(yǔ)言,通過(guò)擴(kuò)展HTML的語(yǔ)法,讓你能更清楚、簡(jiǎn)潔地構(gòu)建你的應(yīng)用組件,需要的朋友可以參考下2014-12-12Angular2生命周期鉤子函數(shù)的詳細(xì)介紹
這篇文章主要介紹了Angular2生命周期鉤子函數(shù)的詳細(xì)介紹,Angular提供組件生命周期鉤子,可以讓我們更好的開發(fā)Angular應(yīng)用,有興趣的可以了解一下2017-07-07使用Angular9和TypeScript開發(fā)RPG游戲的方法
這篇文章主要介紹了使用Angular9和TypeScript開發(fā)RPG游戲的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03AngularJS使用ng-repeat遍歷二維數(shù)組元素的方法詳解
這篇文章主要介紹了AngularJS使用ng-repeat遍歷二維數(shù)組元素的方法,結(jié)合實(shí)例形式分析了AngularJS二維數(shù)組元素遍歷的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11