angular執行圖:
jquery啓動:
js dom元素綁定相應的事件,當dom監聽到相應的事件,這時就開始執行註冊的這個事件.
angularjs執行:
首先,綁定jquery,判斷是否引入jquery,若是沒有引入jquery,本身會實現一個jqlit。
其次,publishExternalApi
2,publishExternalApi 在啓動angular以前首要準備好service,directives...,首先在angular上註冊forEach,bind方法
好比:
2.1須要備案,可以是angular能方便找到你,yourName就是檢索
[]就是依賴css
var APP = angular.module('yourName',[],configFn) angular.module()建立、獲取、註冊angular中的模塊
傳遞參數不止一個,表明新建模塊;空數組表明該模塊不依賴其餘模塊 var createModule = angular.module("myModule", []); 只有一個參數(模塊名),表明獲取模塊,若是模塊不存在,angular框架會拋異常 var getModule = angular.module("myModule"); getModule ==createModule
configFn就是你出生的時候能夠作些初始化之類的動做,好比娃娃大叫...
2.2,出生以後能夠有不少的技能,好比會angular編程,會java...,而後這些技能都須要取個名字...html
var APP = angular.module('yourName',[],configFn) app.controller(xx) factory()... service()... ...
angular.module(name, [requires], [configFn]); name:字符串類型,表明模塊的名稱; requires:字符串的數組,表明該模塊依賴的其餘模塊列表,若是不依賴其餘模塊,用空數組便可; configFn:用來對該模塊進行一些配置。
2.3,有了技能以後要讓人知道,因此要暴露你的技能讓別人來用.java
如在services.js裏面setupModuleLoader在angular上註冊module,controller等api最後返回的是: return(moduleInstance=(_invokeQueue:[],_runBlocks:[],controller factory service...))
2.4,有了技能,別人也已經知道了,而後也準備好了讓別人調用了,首先別人須要遍歷你的技能,把全部的技能都列在一個list invokeQueue上jquery
moduleInstance={_invokeQueue _runBlock}
2.5,技能都掌握在一我的的手裏,他的名字叫ng,下面就是ng的備案:
angularModule('ng',['ngLocal'],['$provide',function ngModule($provide){//ngLocal是ng本身不會的技能,因此要依賴於別人
$provide.provider('$compile',$compileProvider).directive({//compile服務是ng本身的技能angularjs
A:htmlDirective, input:inputDirective, ...
}).directive(ngAttributeAliasDirectives).directive(ngEventDirectives);編程
$provide.provider({ $anchorScroll:$AnchorScrollProvider, $animate:$AnimateProvider, $browser:$BrowserProvider })
}])
3,angularInit
全部的東西都準備好了,如今開始啓動:2種方法啓動
1),ng-app
2),跳過第一步直接 doBootstrap(element,[module])
3.1在解析html的時候,不少directives的技能都是有ng這我的掌握,因此首先要召喚出ng,另外還須要註冊$rootElement,這個由無名氏掌握(放在匿名的空間裏)bootstrap
modules=[ 'ng',['$provide',function($provide){$provide.value('$rootElement',element);
}],'myApp'
]
3.2 全部的技能都調集起來了如今開始決鬥了,首先調用createInjecter,這裏咱們定義2個技能的集合:api
createInjecter(modules) //providerCache存放全部人的技能,無論名字,只管技能 providerCache:{$provider,$injector} //若是調用過了就放在這裏,方便下次尋找,若是須要新的技能就去大庫裏尋找 instanceCache:{$injector}
3.3 遍歷每一個人的invokeQueue數組
.loadModules if:string 遍歷,檢索出module,遍歷invokeQueue,將其技能放在定義好的庫裏面 var invokeArgs = invokeQueue[i], provider = providerInjecter.get(invokeArgs[0]) provider[invokeArgs[1]].apply(provider,invokeArgs[2]); if:function或Array, 直接providerInjector.invoke return runBlocks
3.4 遍歷全部人的技能 遍歷runBlocks
forEach(runBlocks){app
instanceInjector.invoke
}
3.5 編譯全部的dom compile dom
injector.invoke(['$rootScope'...])
demo 執行順序 4,2,3,1 var app = angular.module('demo',[]) app.controller('test',[function(){//放在providerCach裏,等compile服務執行以後才執行 console.log('step1') }]) app.config('test',[function($provide){//其次是config console.log('step2') }]) app.run(function(){ console.log('step3') }) angular.element(document).ready(function(){//首先是dom ready console.log('step4') angular.bootstrap(angular.element(document),['demo']) })
4,angularjs源碼解析
angular源碼是一個自執行函數,當js被加載完以後,當即執行。除了最後一行.
在angular的源碼中,這段代碼不是自執行函數。 !window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
代碼開始執行:
if (window.angular.bootstrap) {//判斷angularjs是否是已經啓動,若是已經啓動了就報錯WARNING: Tried to load angular more than once. //AngularJS is already loaded, so we can return here... console.log('WARNING: Tried to load angular more than once.'); return; } //try to bind to jquery now so that one can write jqLite(document).ready() //but we will rebind on bootstrap again. bindJQuery();//對jquery庫進行綁定 publishExternalAPI(angular);//將angular的api擴展到angular全局函數 jqLite(document).ready(function() { angularInit(document, bootstrap);//啓動angular,默認從document開始啓動 });
咱們在寫angularjs的時候,老是要定義全局的angular函數,好比:
var app = angular.module('app',[])
那麼這個angular的全局函數從哪裏來的呢?
/** @name angular */ angular = window.angular || (window.angular = {}), //若是window.angular有值就返回--> angular = window.angular //若是沒有值 window.angular = {} --> angular = {} 是一個空對象。
angular 是如何調用module函數呢?
angular.module
function publishExternalAPI
extend(angular, {//extend是一個工具函數,複製的做用 'bootstrap': bootstrap, 'copy': copy, 'extend': extend, 'merge': merge, 'equals': equals, 'element': jqLite, 'forEach': forEach, 'injector': createInjector, 'noop': noop, 'bind': bind, 'toJson': toJson, 'fromJson': fromJson, 'identity': identity, 'isUndefined': isUndefined, 'isDefined': isDefined, 'isString': isString, 'isFunction': isFunction, 'isObject': isObject, 'isNumber': isNumber, 'isElement': isElement, 'isArray': isArray, 'version': version, 'isDate': isDate, 'lowercase': lowercase, 'uppercase': uppercase, 'callbacks': {counter: 0}, 'getTestability': getTestability, '$$minErr': minErr, '$$csp': csp, 'reloadWithDebugInfo': reloadWithDebugInfo });