本版本的重要更新是完全实现AMD规范。整个框架根据此新加载器重写,因此可以方便调用老外用AMD规范写好的JS库了.
有关本模块加载系统的使用,可以到这里详看教程.新加载器是同时支持AMD与玉伯搞的seajs的CMD.如果你在模块定义中的回调带有"require","exports","modules"中的任两个,加载器就视为CMD.不过无视是AMD与CMD,函数里面require, modules, exports都是可用的,完全可以像node.js这样加载模块.
有关require方法的模块标识,可以见这里
有关为什么要用AMD来管理我们的脚本,我想做过一些大项目的人应该心中有数,这不是一个合并JS所能取替的,详见此文。
下面揭载我的加载器的运作机理,姑且从一个没有依赖的模块着手,比如
$.require(
"$lang_fix"
,
function
(){
console.log(
"xxxxxxxxxxxxxx"
)
})
|
不用说,进入$.require(希望大家看这东西时,打开源码对照着看。)
String(list).replace( $.rword,
function
(el){
})
el =
"$lang_fix"
|
进入Module._resolveFilename
url = $.core.base + el +
".js"
|
初次加载,肯定没有在modules中注册, modules[url]为undefined
于是进入 loadJS( url, id );
第二个节点视情况不同分别绑定onreadystatechange, onload, onerror
值得注意的是我们在注册模块时state还是为undefined,它会在innerDefine中修改state。
然后我们通过iframe中的script加载模块,而模块一般是这样的格式
define(
"lang_fix"
,
function
( ){
//==========略============
})
|
这里的define实质上是innerDefine
innerDefine里面做了几个很重要的事情(我们现在只需看第一,第二)
在第二事情中,我们将模块的状态修改了,于是节点执行onreadystatechange/onload时
if
(/loaded|complete|undefined/i.test(
this
.readyState) }{
Ns._checkDeps();
Ns._checkFail(self.document, nick);
}
|
Ns._checkFail发挥效力
_checkFail :
function
( doc, id, error ){
doc && (doc.ok = 1);
if
( error || !modules[ id ].state ){
this
.log(
"Failed to load [[ "
+id+
" ]]"
+modules[ id ].state);
}
},
|
如果是死链,那无法调用define函数,也就无法调用innerDefine,状态为undefine
!modules[ id ].state == true,于是打印错误日志,当然以后我们讨论一下,是不是该throw
如果在旧式opera,它是会无法进入onreadystatechange, onload, onerror任一回调
在_checkFail中,我们会修复doc.ok = 1,那么在iframe中onload中我们检测doc.ok不等于1时,
就在_checkFail传入第三个参数true,让它打印错误日志
如果在FF,chrome, IE9,它们就会进入onerror回调,那里的调用代码中
Ns._checkFail(self.document, nick,
true
)
|
因此也顺利检测到死链。
反正只要加载失败,我们就立即把对应iframe移出DOM树!
好了,如果成功加载,我们就通过innerDefine到达$.define,并也把对应iframe移出DOM树
$.define干了如下几个事情
比如
define({
aaa:2
})
|
经上面几次转换,依次变为
aaa:2
});
//---->
aaa:2
});
//---->
return
{
aaa:2
}
});
//---->
$.require([],
function
(){
return
{
aaa:2
}
|
最后我们将参数的顺序重排一下,再次调用$.require
//0,1,2 --> 1,2,0
this
.require( args[1], args[2], parent );
|
由于lang_fix是没有依赖的,因此dn === cn 相当于 0 == 0,执行install( id, args, factory );
install简而言之是将模块工厂执行,将state改为2。
我们还需要注意一下,我们每次调用$.require或加载一个脚本时都执行_checkDeps方法。
当lang_fix的状态改为2后
$.require(
"$lang_fix"
,
function
(){
console.log(
"xxxxxxxxxxxxxx"
)
})
|
这个回调也将执行!
控制台打印xxxxxxxxxxxxxxxx
源码位于这里