Angularjs 源码分析-setupModuleLoader
setupModuleLoader源码结构
下面是setupModuleLoader的源码结构部分(省略掉的部门会在后面详细讲解)
function setupModuleLoader(window) {//省略...function ensure(obj, name, factory) {return obj[name] || (obj[name] = factory());}var angular = ensure(window, 'angular', Object);angular.$$minErr = angular.$$minErr || minErr;return ensure(angular, 'module', function() {var modules = {};return function module(name, requires, configFn) {var assertNotHasOwnProperty = function(name, context) {if (name === 'hasOwnProperty') {throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);}};assertNotHasOwnProperty(name, 'module');if (requires && modules.hasOwnProperty(name)) {modules[name] = null;}return ensure(modules, name, function() {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);}var invokeQueue = [];var configBlocks = [];var runBlocks = [];var config = invokeLater('$injector', 'invoke', 'push', configBlocks);var moduleInstance = {// Private state_invokeQueue: invokeQueue,_configBlocks: configBlocks,_runBlocks: runBlocks,requires: requires,name: name,provider: invokeLaterAndSetModuleName('$provide', 'provider'),factory: invokeLaterAndSetModuleName('$provide', 'factory'),service: invokeLaterAndSetModuleName('$provide', 'service'),value: invokeLater('$provide', 'value'),constant: invokeLater('$provide', 'constant', 'unshift'),decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),config: config,run: function(block) {runBlocks.push(block);return this;}};if (configFn) {config(configFn);}return moduleInstance;function invokeLater(provider, method, insertMethod, queue) {//省略...}function invokeLaterAndSetModuleName(provider, method) {//省略...}});};});}
接下来,我们针对上述代码逐一解析
ensure
function ensure(obj, name, factory) {return obj[name] || (obj[name] = factory());}
该函数实现了module的getter和setter功能,在整个setupModuleLoader中被广泛使用了
invokeLater 和 invokeLaterAndSetModuleName
function invokeLater(provider, method, insertMethod, queue) {if (!queue) queue = invokeQueue;return function() {queue[insertMethod || 'push']([provider, method, arguments]);return moduleInstance;};
}function invokeLaterAndSetModuleName(provider, method) {return function(recipeName, factoryFunction) {if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;invokeQueue.push([provider, method, arguments]);return moduleInstance;};
}
顾名思义就是延迟执行的意思,先把要执行的对象(provider),要执行的方法(method),以及执行参数(auguments)都保存到queue中,在后面的代码分析中我们会分析另外一个函数loadmodules,也就是在loadmodules才真正执行
函数最后返回moduleInstance可以实现链式调用
invokeLaterAndSetModuleName相比invokeLater,默认queue为invokeQueue,并且保存了module的名字在$$moduleName,通过源码我们总结出
| module方法 | provider | method | queue | insertMethod |
|---|---|---|---|---|
| config | $injector | invoke | configBlocks | push |
| provider | $provider | provider | invokeQueue | push |
| factory | $provider | factory | invokeQueue | push |
| service | $provider | service | invokeQueue | push |
| value | $provider | value | configBlocks | push |
| constant | $provider | constant | configBlocks | unshift |
| animation | $animateProvider | register | invokeQueue | push |
| filter | $filterProvider | register | invokeQueue | push |
| controller | $controllerProvider | register | invokeQueue | push |
| directive | $compileProvider | directive | invokeQueue | push |
setupModuleLoader私有变量
假设有一个module app,var app = angular.module('app',[...])
- invokeQueue
类型为数组,主要用来保存调用app.controller,app.service,app.directive…等方法的参数,具体方法见上表
比如调用
app.controller('testCtrl',["\$rootScope",function(\$scope){...}])
invokeQueue就会增加一条记录
["$controllerProvider","register",['testCtrl',["\$rootScope",function(\$scope){...}]]]
- configBlocks
类型为数组,主要用来保存类似app.config(),app.value()
给module配置信息,支持两种方式,一种就是上面的app.config,还有一种就是定义的时候,第三个参数就是配置函数,如下
var app = angular.module('app',[],['xxx',function(xxx){}])
invokeQueue和configBlocks在loadModules中都被同一个方法调用了一次,调用顺序不一样
//省略if (isString(module)) {moduleFn = angularModule(module);runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);runInvokeQueue(moduleFn._invokeQueue);runInvokeQueue(moduleFn._configBlocks);//省略
- runBlocks
类型为数组,主要用来保存app.run()中run里面的内容
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
