module模块 - acelan86/angular GitHub Wiki
angular.module哪来的?
看下面的代码:
publishExternalAPI(angular); //加载angular时调用#14482
//publishExternalAPI定义 #1346
function publishExternalAPI(angular){
...
angularModule = setupModuleLoader(window);
...
}
/**
* setupModuleLoader定义 #1079
* 这个方法起始就是达到下面的效果:
* 1. window.anguler.module = function module(name, require, configFn) {};
* 2. 闭包了一个modules用来缓存已经初始过的模块
*/
function setupModuleLoader(window) {
...
return ensure(ensure(window, 'angular', Object), 'module', function() {
var modules = {}; //用来缓存已经加载的模块
...
return function module(name, requires, configFn) {
//这里为了结构方便看,内容拉到后面去解释
};
});
}
/**
* 主角来了,API:anguler.module方法
* 它做了下面几点:
* 1. 如果有同名不同依赖的模块声明,则重新定义一个新模块,放弃原有那个
* 2. module[name] = moduleInstance
* 3. 处理configFn
* 4. return module[name], 就是本次生成的moduleInstance
*/
function module(name, requires, configFn) {
//#1
if (requires && modules.hasOwnProperty(name)) {
modules[name] = null;
}
//#2,3,4
return ensure(modules, name, function() {
//不是用function ModuleInstance来声明对象,而是用一个对象字面量来处理
var moduleInstance = {
//moduleInstance的属性及方法见后面定义...
};
//主调用对象为$injector,调用方法是invoke,用来获取依赖注入,并执行方法。区别其他provider,如moduleInstance的provider,factory,controller等,他们的主调用对象是$provider。
var config = invokeLater('$injector', 'invoke');
if (configFn) {
config(configFn); //module方法的第三个参数,如有,则将方法注入invokeQueue,在loadModule的时候执行
}
return moduleInstance;
/*
每个module实例方法基本上都是调用这货来实现的
顾名思义,延后调用,那延后到什么时候调用?先放着吧。。
这里的用处就是往moduleInstance的_invokeQueue里面push进我要延后做的方法(记录了方法提供者,方法名,参数)。
最后返回这个moduleInstance实现链式调用
*/
function invokeLater(provider, method, insertMethod) {
return function() {
invokeQueue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
}
}
});
}
//moduleInstance
var moduleInstance = {
_invokeQueue: invokeQueue, //调用队列,createInjector时调用的loadModules方法中使用
_runBlocks: runBlocks, //这货反正现在看不出干嘛
requires: requires, //模块依赖没有被处理,直接放入module的实例属性中
name: name,
//各种在module实例化后可以执行的接口方法在这里声明
provider: invokeLater('$provide', 'provider'),
factory: invokeLater('$provide', 'factory'),
service: invokeLater('$provide', 'service'),
value: invokeLater('$provide', 'value'),
constant: invokeLater('$provide', 'constant', 'unshift'),
filter: invokeLater('$filterProvider', 'register'),
controller: invokeLater('$controllerProvider', 'register'),
directive: invokeLater('$compileProvider', 'directive'),
config: config, //invokeLater('$injector', 'invoke'),
run: function(block) {
runBlocks.push(block);
return this;
}
};
声明module和在module上声明controller
理解了上面的来源,接下来,写我们的angular程序,从app.js入手
angular.module('yeomanApp', [])
...
按上面的module function的分析,这时候结果是闭包的modules缓存里面加入了modules['yeomanApp'] = moduleInstance;
然后我们往下走,再module上定义一个controller:
angular.module('yeomanApp', [])
.controller('UserCtrl', ['$scope', function ($scope) {
console.log($scope);
}]);
即调用模块声明后生成的moduleInstance的controller方法, 即: 执行invokeLater('$controllerProvider', 'register')('UserCtrl', ....), 即完成下面两个步骤:
- moduleInstance._invokeQueue.push('$controllerProvider', 'register', ['UserCtrl', ...])
- 返回moduleInstance供链式调用
注意,这里仅仅是将生成controller的controllerProvider的register方法写到module的调用队列(invokeQueue)中,没有做其他更多的操作。