angularJS加载进来后,会有一个当即执行函数调用,在源代码的最下面是angular初始化的地方。代码展现:html
bindJQuery(); publishExternalAPI(angular); jqLite(document).ready(function() { angularInit(document, bootstrap); });
bindJQuery方法的做用是:检查你的主页面是否引用了jquery,没有的话,就用angular自己自带的JQLite,不然使用你引用的jquery。jquery
function bindJQuery() { jQuery = window.jQuery; //若是在主页面加载了jQuery库,这里的jQuery就会存在 if (jQuery) { jqLite = jQuery; ...... } else { jqLite = JQLite; //若是没有引用jQuery库,就使用自带的JQLite。 } angular.element = jqLite; //把结果赋给angular.element上 }
publishExternalAPI方法的做用是:首先绑定一些方法到angular对象上,而后就是初始化angular核心的模块。bootstrap
function publishExternalAPI(angular){ extend(angular, { //绑定方法到angular对象上 'bootstrap': bootstrap,
'extend': extend,
'element': jqLite,
'injector': createInjector, ...... }); angularModule = setupModuleLoader(window); // 此方法会把angular对象绑定到window上,而后把一个函数绑定到angular的module属性上,最后返回这个函数,这个函数是一个模块加载器,主要做用是建立和获取模块。这里的angularModule函数就是angular.module函数。 try { angularModule('ngLocale'); } catch (e) { angularModule('ngLocale', []).provider('$locale', $LocaleProvider); //建立一个名为ngLocale的模块,并在这个模块上定义一个名为$locale的$LocaleProvider服务提供者。这里的provider方法,是把方法中的参数都存到invokeQueue数组中,以便在后面调用,从setupModuleLoader方法中很容易知道。 } angularModule('ng', ['ngLocale'], ['$provide', //建立一个名为ng的模块,这个模块依赖于ngLocale模块。 function ngModule($provide) { $provide.provider({ $$sanitizeUri: $$SanitizeUriProvider }); $provide.provider('$compile', $CompileProvider). //ng模块中,定义一个名为$compile的$CompileProvider服务提供者 directive({ a: htmlAnchorDirective, input: inputDirective, textarea: inputDirective, form: formDirective, option: optionDirective, ngBind: ngBindDirective, ngClass: ngClassDirective, ngController: ngControllerDirective, ngForm: ngFormDirective, ngHide: ngHideDirective, ngIf: ngIfDirective, ngInit: ngInitDirective, ngRepeat: ngRepeatDirective, ngShow: ngShowDirective, ngOptions: ngOptionsDirective, ngTransclude: ngTranscludeDirective, ngModel: ngModelDirective, ngList: ngListDirective, ngChange: ngChangeDirective, required: requiredDirective, ngRequired: requiredDirective, ngValue: ngValueDirective }); $provide.provider({ //在ng模块中,定义一系列的服务提供者 $animate: $AnimateProvider, $controller: $ControllerProvider, $filter: $FilterProvider, $http: $HttpProvider, $location: $LocationProvider, $parse: $ParseProvider, $rootScope: $RootScopeProvider, $window: $WindowProvider }); } ]); }
setupModuleLoader方法的源码:数组
function setupModuleLoader(window) {
function ensure(obj, name, factory) {
return obj[name] || (obj[name] = factory());
}
var angular = ensure(window, 'angular', Object); //设置window.angular等于一个空对象
return ensure(angular, 'module', function() { //把angular.module设置成这个module函数,并返回这个函数。
var modules = {};
return function module(name, requires, configFn) { //当咱们经过var demo1 = angular.module('demoApp', []);建立一个模块时,它返回的是moduleInstance。而这个moduleInstance对象有factory(),controller(),directive(),config(),run()等方法能够调用。
if (requires && modules.hasOwnProperty(name)) { //若是有同名的模块已经建立过,就把之前的那个模块删除。这里使用的是一个闭包,由于每次调用angular.module进行模块的建立时,访问的modules对象是在外层的匿名函数中定义的,原本一个函数执行结束后,就会销毁里面的变量,虽然这里匿名函数已经执行结束了,可是因为内部函数module引用了此变量modules,因此即使外层的匿名函数执行结束了,它里面定义的modules变量也不会销毁。经过闭包,咱们能够定义一个私有的变量modules,只能经过规定的方法angular.module进行访问,外部没法操做这个私有的变量modules。 modules[name] = null; } return ensure(modules, name, function() { //modules[demoApp] = moduleInstance,并返回这个moduleInstance。 var invokeQueue = []; var runBlocks = []; var config = invokeLater('$injector', 'invoke'); var moduleInstance = { //模块实例的方法 requires: requires, provider: invokeLater('$provide', 'provider'), factory: invokeLater('$provide', 'factory'), service: invokeLater('$provide', 'service'), value: invokeLater('$provide', 'value'), constant: invokeLater('$provide', 'constant', 'unshift'), animation: invokeLater('$animateProvider', 'register'), filter: invokeLater('$filterProvider', 'register'), //当咱们经过一个模块实例建立一个过滤器时,调用的是invokeLater方法返回的匿名函数function(){ invokeQueue['push']([$filterProvider, register, arguments]); return moduleInstance; } controller: invokeLater('$controllerProvider', 'register'), directive: invokeLater('$compileProvider', 'directive'), config: config, run: function(block) { runBlocks.push(block); return this; } };
if(configFn){ //当调用angular.module方法传入了三个参数时,就会执行config方法,上面在定义ng模块时,就会传入第三个参数。
config(configFn); //config方法其实就是invokeLater方法执行后的返回值。这里执行以后,也是对数组invokeQueue进行push操做。当ng模块建立时,invokeQueue = [ [ $injector, invoke, [[$provide, function ngModule(){}]] ] ]。
}
return moduleInstance; function invokeLater(provider, method, insertMethod) { return function() { invokeQueue[insertMethod || 'push']([provider, method, arguments]); return moduleInstance; }; } }); }; }); }
咱们举个例子说下上面的源码:闭包
var demo1 = angular.module('demoApp', []); demo1.filter('reverse', function(){ 当调用此方法时,其实就是调用invokeQueue["push"]()方法,而且返回此模块实例,以便进行链式操做。好比:demo1.filter().directive()。当调用demo1的filter方法时,这里会执行invokeQueue["push"]([ $filterProvider, register, ["reverse", function(){}] ]),而这只是一个数组的push操做,也就是说,invokeQueue = [ [ $filterProvider, register, ["reverse", function(){}] ] ]; return function(input, uppercase) { var out = ""; for (var i = 0; i < input.length; i++) { out = input.charAt(i) + out; } if (uppercase) { out = out.toUpperCase(); } return out; } });
publishExternalAPI方法讲完以后,接下来就是app
jqLite(document).ready(function() { //文档加载完成后,执行angularInit方法,咱们常常说的:文档加载完成后,angular才启动的意思就是在这里。 angularInit(document, bootstrap); });
function angularInit(element, bootstrap) { var elements = [element], appElement, module, names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'], //angular有4种方式在页面上定义angular应用 NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/; function append(element) { element && elements.push(element); } forEach(names, function(name) { names[name] = true; append(document.getElementById(name)); name = name.replace(':', '\\:'); if (element.querySelectorAll) { forEach(element.querySelectorAll('.' + name), append); forEach(element.querySelectorAll('.' + name + '\\:'), append); forEach(element.querySelectorAll('[' + name + ']'), append); } }); //针对4种定义方式,在页面上获取定义为angular应用的元素节点, forEach(elements, function(element) { if (!appElement) { //appElement只定义一次 var className = ' ' + element.className + ' '; var match = NG_APP_CLASS_REGEXP.exec(className); if (match) { appElement = element; module = (match[2] || '').replace(/\s+/g, ','); } else { forEach(element.attributes, function(attr) { if (!appElement && names[attr.name]) { appElement = element; module = attr.value; } }); } } }); //定义angular应用的元素,也就是在页面上写有ng-app(有4种方式定义)的元素定义为appElement。 if (appElement) { bootstrap(appElement, module ? [module] : []); //若是页面上有定义angular应用的元素,就启动。 } }
function bootstrap(element, modules) { var doBootstrap = function() { //定义一个函数 element = jqLite(element); if (element.injector()) { //若是此元素的angular应用已经启动过了,就抛出错误 var tag = (element[0] === document) ? 'document' : startingTag(element); throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag); } modules = modules || []; modules.unshift(['$provide', function($provide) { $provide.value('$rootElement', element); }]); modules.unshift('ng'); //这里,咱们假设在页面上定义了ng-app的元素,没有添加任何的多余的东西。所以这里的modules=["ng",["$provide",function($provide){}]]。 var injector = createInjector(modules); //这个方法很是重要,它把咱们angular应用须要初始化的模块数组传进去后,进行加载,并建立一个注册器实例对象,最后返回这个注册器实例对象。 injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate', //调用注册器实例对象的invoke方法 function(scope, element, compile, injector, animate) { scope.$apply(function() { element.data('$injector', injector); compile(element)(scope); }); }] ); return injector; }; var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { //若是window.name不是以NG_DEFER_BOOTSTRAP!开头的话,就进入if语句,执行上面定义的方法。 return doBootstrap(); } window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); angular.resumeBootstrap = function(extraModules) { forEach(extraModules, function(module) { modules.push(module); }); doBootstrap(); }; }
上面的invoke方法执行后,会调用compile方法,此方法里面会先生成编译实例,而后经过编译实例去编译应用的元素,编译的核心是生成指令对应的link函数。ide
加油!函数