启动过程

第3部分:

1.var angular = window.angular || (window.angular = {})
2.

if (window.angular.bootstrap) {
//AngularJS is already loaded, so we can return here...
console.log('WARNING: Tried to load angular more than once.');
return;
}
3.
bindJQuery();
3.1.
if (jQuery && jQuery.fn.on)
yes:
no:jqLite = JQLite;
3.2. jqLite = JQLite;
4.
publishExternalAPI(angular);
4.1.
extend(angular, {
'bootstrap': bootstrap,
'copy': copy,
4.2. angularModule = setupModuleLoader(window);

ensure:
function ensure(obj, name, factory) {
if (obj[name]) {
return obj[name];
} else {
return obj[name] = factory();
}
}
第一层 :
1.var modules = {}; 2.
return function module(name, requires, configFn) {
//.......
};
5. 
angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
function getDecimals(n) {
6.jqLite(document).ready(function() {
angularInit(document, bootstrap);
});

第5部分:

从上到下分为7步:
第1步:
function module(name, requires, configFn) {
var assertNotHasOwnProperty = function(name, context) {
if (name === 'hasOwnProperty') {
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
}
};
1.1.
var assertNotHasOwnProperty = function(name, context) {
if (name === 'hasOwnProperty') {
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
}
};
1.2.
assertNotHasOwnProperty(name, 'module');
if (requires && modules.hasOwnProperty(name)) {
modules[name] = null;
}
1.3.

2.
if (!requires) {
throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
"the module name or forgot to load it. If registering a module ensure that you " +
"specify the dependencies as the second argument.", name);
}
2.1.
if (!requires) {
throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
"the module name or forgot to load it. If registering a module ensure that you " +
"specify the dependencies as the second argument.", name);
}
2.2.
/** @type {!Array.<Array.<*>>} */
var invokeQueue = [];
/** @type {!Array.<Function>} */
var configBlocks = [];
/** @type {!Array.<Function>} */
var runBlocks = [];

2.3.var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
2.4.
/** @type {angular.Module} */
var moduleInstance = {
// Private state
_invokeQueue: invokeQueue,
_configBlocks: configBlocks,
_runBlocks: runBlocks,

_invokeQueue: invokeQueue,_configBlocks: configBlocks,_runBlocks: runBlocks,requires: requires,name: name,
provider: invokeLaterAndSetModuleName('$provide', 'provider'),
2.5.if (configFn) {config(configFn);}
2.6.return moduleInstance;
第2步:

provider: invokeLaterAndSetModuleName('$provide', 'provider'),
function invokeLaterAndSetModuleName(provider, method) {
return function(recipeName, factoryFunction) {
if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
invokeQueue.push([provider, method, arguments]);
return moduleInstance;
};
}

return function(recipeName, factoryFunction) {
if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
invokeQueue.push([provider, method, arguments]);
return moduleInstance;
};
第3,4,5步:

第6步:

从右到左的代码:
1.var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
2.function invokeLater(provider, method, insertMethod, queue) {
if (!queue) queue = invokeQueue;
return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};}
3.return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};
4.return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};
第7步:
run: function(block) {
runBlocks.push(block);
return this;
}
第7部分:

1.forEach(ngAttrPrefixes, function(prefix) {
var name = prefix + 'app';
var candidate;
if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
appElement = candidate;
module = candidate.getAttribute(name);
}});
2.if (appElement) {
config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
bootstrap(appElement, module ? [module] : [], config);
}

核心代码:var doBootstrap = function() {
element = jqLite(element);
if (element.injector()) {
1.if (element.injector()) {
var tag = (element[0] === document) ? 'document' : startingTag(element);
//Encode angle brackets to prevent input from being sanitized to empty string #8683
throw ngMinErr(
'btstrpd',
"App Already Bootstrapped with this Element '{0}'",
tag.replace(/</,'<').replace(/>/,'>'));
}
2.modules.unshift(['$provide', function($provide) {
$provide.value('$rootElement', element);
}]);
3.var injector = createInjector(modules, config.strictDi);

3.1.providerCache = {
$provide: {
provider: supportObject(provider),
factory: supportObject(factory),
service: supportObject(service),
value: supportObject(value),
constant: supportObject(constant),
decorator: decorator
}
},
3.2.providerInjector = (providerCache.$injector =
createInternalInjector(providerCache, function(serviceName, caller) {
if (angular.isString(caller)) {
path.push(caller);
}
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
})),
3.2.2.function createInternalInjector(cache, factory) {
function getService(serviceName, caller) {
if (cache.hasOwnProperty(serviceName)) {
3.3.instanceCache = {},
3.4.instanceCache = {},
instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(serviceName, caller) {
var provider = providerInjector.get(serviceName + providerSuffix, caller);
return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
}));

3.5.forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
3.5.1.

1.1.if (loadedModules.get(module)) return;
loadedModules.put(module, true);
1.2.if (isString(module)) {
moduleFn = angularModule(module);
runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
runInvokeQueue(moduleFn._invokeQueue);
runInvokeQueue(moduleFn._configBlocks);
}
1.2.1.moduleFn = angularModule(module);
1.2.2.loadModules(moduleFn.requires)
1.2.3.runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
1.3. else if (isFunction(module)) {
runBlocks.push(providerInjector.invoke(module));
} else if (isArray(module)) {
runBlocks.push(providerInjector.invoke(module));
}
4.
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
function bootstrapApply(scope, element, compile, injector) {
scope.$apply(function() {
element.data('$injector', injector);
compile(element)(scope);
});
}]
);

function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
previousCompileContext) {
if (!($compileNodes instanceof jqLite)) {
4.1.var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext);

1.1.directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
ignoreDirective);
1.2.childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
!(childNodes = nodeList[i].childNodes) ||
!childNodes.length)
? null
: compileNodes(childNodes,
1.3.if (nodeLinkFn || childLinkFn) {
linkFns.push(i, nodeLinkFn, childLinkFn);
linkFnFound = true;
nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
}
4.2.

unction compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
var stableNodeList;
4.2.1.controllerScope = scope;
if (newIsolateScopeDirective) {
isolateScope = scope.$new(true);
} else if (newScopeDirective) {
controllerScope = scope.$parent;}
4.2.2.// Initialize bindToController bindings
for (var name in elementControllers) {
var controllerDirective = controllerDirectives[name];
var controller = elementControllers[name];
var bindings = controllerDirective.$$bindings.bindToController;
4.2.3.// POSTLINKING
for (i = postLinkFns.length - 1; i >= 0; i--) {
linkFn = postLinkFns[i];
invokeLinkFn(linkFn,
linkFn.isolateScope ? isolateScope : scope,
$element,

浙公网安备 33010602011771号