You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
var assertNotHasOwnProperty = function(name, context) {
if ("hasOwnProperty" === name) throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context)
};
这里注意的是对比的modules对象,是在这个里面的 var modules = {};
它并不是全局的,而是只是在闭包**function(name, requires, configFn){}**局部作用域的。但由于是在闭包里面,所以它会一直保存在作用域中,相当于一直被缓存,不会被释放掉。
继续往下面看 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);
而requires如果为空,则表示是获取已有的模块
但如果requires不是空而是根本不存在,也就是说没有定义过这个module
setupModuleLoader其实看字面意思就可以知道它为模板加载器,就是为module设置加载器
function setupModuleLoader(window) {}
首先传入了window对象,作用为为后面ensure判断window全局对象是否含有属性angular
这里有个闭包函数,作用是判断对象中是否存在某个属性,没有的话创建对应的方法,并执行该方法
所以下面就会看到
ensure(ensure(window, "angular", Object), "module", function() {})
第一个ensure创建了为window对象创建angular
window.angular = Object()
第二个ensure创建了为angular对象创建module
到此步往下再看其实就变成了这样了
angular.module = function module(name,require,configFn);
这里就是我们常用到的模块加载部分
当我们angular.module('wscatApp'),只传一个参数,为getter操作,返回moduleInstance
当我们angular.module('wscatApp',[]) ,传了requires数组(空数组也行),为setter操作,也是返回对象moduleInstance
这两者有什么不同呢,可以看到module方法可以传递三个参数第二个参数require就是我们需要注入的依赖数组,其实就是注入所谓的DI
什么是DI呢,DI就是依赖注入
详情可以看这篇文章阐述
Javascript DI!Angular依赖注入的实现原理
截取里面几句话,方便这里的理解
这里的模块包括控制器、服务、过滤器、指令等子元素组成的整体
具体看源码这部分
再往下看,里面有个闭包函数
这句也挺可爱的,module名称是不能以hasOwnProperty命名,否则会抛出”badname“的错误提醒。
下面继续执行
assertNotHasOwnProperty(name, "module"), requires && modules.hasOwnProperty(name) && (modules[name] = null), ensure(modules, name, function() {})
由于这里有多个异或操作,其实简单看起来就是进行了如下操作
这里很容易看出来,如果有传入requires数组(就算是空数组)还有modules对象里面有已定义好的对象或者属性,则会删除已有的module信息,将其置为null,并重新定义该属性
这里注意的是对比的modules对象,是在这个里面的
var modules = {};
它并不是全局的,而是只是在闭包**function(name, requires, configFn){}**局部作用域的。但由于是在闭包里面,所以它会一直保存在作用域中,相当于一直被缓存,不会被释放掉。
继续往下面看
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);
而requires如果为空,则表示是获取已有的模块
但如果requires不是空而是根本不存在,也就是说没有定义过这个module
看到上面这部分源码后启示我们在创建模块时,就算没有依赖其他模块,写法也应该是:
angular.module('wscatApp', []);
否则会到这里报错
angular.module('wscatApp',[...])和angular.module('wscatApp')
区别在于
到这一步就是介绍这部分的最后一个闭包函数
invokeLater从字面意思不难看出是之后再调用
理解这里我决定用一段简单的代码来阐述
实际上我们还可以这样写
app.controller('serCtrl', function($scope, cat) {})
的controller运行了moduleInstance对象中的的invokeLater函数
controller: invokeLater("$controllerProvider", "register")
invokeLater传递三个参数
所以实际上变成了这样invokeQueue.push()
invokeQueue[insertMethod || "push"]([provider, method, arguments])
invokeQueue默认队列操作是push,如果有传入其他insertMethod
constant: invokeLater("$provide", "constant", "unshift")
则是unshift操作
animation: invokeLater("$animateProvider", "register")
则是register操作
由于
return invokeQueue[insertMethod || "push"]([provider, method, arguments]), moduleInstance
最后执行队列存放之后,会返回invokeQueue,所以后面可以进行链式操作,例如这样app.controller().factory()
其他的模块和实例如下
举一反三,这里就不继续展开写了,引入AngularJS模块详解写的列表,如下
angular模块实例属性和方法
属性
name
模块的名字。
方法
模块的以下方法最后全部会返回模块实例本身,形成执行链。
看最后一句
return configFn && config(configFn), moduleInstance
这句转化成这样容易点理解
也就是如果声明module时存在第三个参数,那么就把第三个参数的设置放进invokeQueue队列中。这样,就可以在载入一个module的时候同时做一些其他的事情。
config = invokeLater("$injector", "invoke")
config(configFn)
invokeLater("$injector", "invoke")(configFn)
The text was updated successfully, but these errors were encountered: