启动过程
在angular启动过程中会经历以下步骤:
publishExternalAPI
函数中会加载扩展函数,定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
### angularInit
angularInit函数中会调用```bootstrap```,bootstrap中会调用```createInjector```方法完成依赖注入,然后调用```invoke```启动编译服务
```js
////通过createInjector方法会调用注入时提供的ng模块中的configFn
//configFn中提供了$rootScope, $rootElement, $compile, $injector
//通过$provide.provider方法提供
//modules中首先就是ng模块
var injector = createInjector(modules, config.strictDi);
//$rootScope,$rootElement,$compile,$injector都是在publishExternalAPI中
//注入ng模块时由$provide.provider提供的
//$rootElement在bootstrap中
// modules.unshift(['$provide', function($provide) {
// $provide.value('$rootElement', element);
// }]);
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
function bootstrapApply(scope, element, compile, injector) {
scope.$apply(function() { //rootScope
element.data('$injector', injector);
compile(element)(scope);
});
}]
);
createInjector
1 | var runBlocks = loadModules(modulesToLoad); |
loadModules是createInjector内部方法,方法中会调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31获取模块。
因为定义ng模块时是push到configBlocks中的,所以会直接调用runInvokeQueue
### runInvokeQueue
```js
//queue就是在定义ng 模块时因为有configFn参数,然后调用config 函数(实际是通过invokeLater返回的函数)push到configBlocks中。
var config = invokeLater('$injector', 'invoke', 'push', configBlocks);//configBlocks此时为空
function invokeLater(provider, method, insertMethod, queue) {
if (!queue) queue = invokeQueue;
return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};
}
//此时queue就是['$injector','invoke',[['$provide',function($provide){}]]]
function runInvokeQueue(queue) {
var i, ii;
for (i = 0, ii = queue.length; i < ii; i++) {
var invokeArgs = queue[i],
//loadModules为内部方法所以能直接调用providerInjector
//get方法就是返回injector对象的getService方法
provider = providerInjector.get(invokeArgs[0]);
//实际就是调用$injector的invoke方法
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
}
}
invoke函数
1 | //调用runInvokeQueue时,fn就是['$provide',function($provide){}] |
providerCache
$provide提供了provider方法,比如1
2
3
4
5
6
7
8
9
10
11
12
13
14
```js
//providerInjector调用invoke函数时,getService
//是从providerCache中获取的
var providerCache = {
$provide: {
provider: supportObject(provider),
factory: supportObject(factory),
service: supportObject(service),
value: supportObject(value),
constant: supportObject(constant),
decorator: decorator
}
};
provider
1 | //name $compile |
provider方法里其实调用了1
2
3
4
5
6
7
8
9
10
11
12```js
//Type就可能是函数类型
function instantiate(Type, locals, serviceName) {
// Check if Type is annotated and use just the given function at n-1 as parameter
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
var args = injectionArgs(Type, locals, serviceName);
// Empty object at position 0 is ignored for invocation with `new`, but required.
args.unshift(null);
//这样构造。。返回函数本身的对象,然后就可以链式调用了。
return new (Function.prototype.bind.apply(ctor, args))();
}