此方法就是调用loadJs方法动态下载a.js文件。(因为有a和jquery,所以会新建两个script),这里有一个疑问,新建a的script,并添加到head中,就会下载js文件,但是在seajs中,并没有下载,而是等jquery的script建立好,并添加到head中,才会下载(谷歌调试器设断点,一直显示pending等待中)。这是为毛?
(推荐看这里:,这里我说下额外的问题,大家可能知道为什么我们要少用table来布局,因为table在呈现树布局的时候,需要多次计算,而div只需要一次。同时,美的电商面试官告诉我:table需要全部解析完才会显示出来,而div解析多少就显示多少。经查证table中如果有tbody标签,就会按照tbody来分段显示。因此在IE6,7,8中,如果你用innerHTML来创建一个"<table></table>",会自动在里面添加<tbody></tbody>。)。
下载成功后,就会解析执行,执行的是define方法。这里会先执行a模块的代码。
define(id,deps,function(){})方法解析
复制代码 代码如下:
//define 定义 ,id : 模块id , deps : 模块依赖 , factory
Module._define = function(id, deps, factory) {
//解析依赖关系 // 如果deps不是数组类型,同时factory是函数
if (!util.isArray(deps) && util.isFunction(factory)) { // 函数体内正则匹配require字符串,并形成数组返回赋值给deps
deps = util.parseDependencies(factory.toString())
}
//设置元信息
var meta = { id: id, dependencies: deps, factory: factory }
if (document.attachEvent) {
// 得到当前script的节点
var script = util.getCurrentScript()
// 如果script节点存在
if (script) {
// 得到原始uri地址
derivedUri = util.unParseMap(util.getScriptAbsoluteSrc(script)) }
if (!derivedUri) {
util.log('Failed to derive URI from interactive script for:', factory.toString(), 'warn')
}
}
.........
}
define首先会对factory执行一个判断 ,判断它是否为一个函数(原因是因为define内也可以包括文件,对象)
如果是函数 , 那么 就会通过factory.toString(),得到函数,并通过正则匹配得 a.js的依赖,并把依赖保存在 deps 中
对于 a.js 而言, 它的依赖 是 b.js 所以 deps为 ['./b']
并对 a.js 的信息进行保存 var meta = { id: id, dependencies: deps, factory: factory }
针对a.js meta = { id : undefined , dependencies : ['./b'] , factory : function(xxx){xxx}}
在 ie 6-9 浏览器中可以拿到当前运行js的路径 但是在标准浏览器中 ,这不可行 ,所以暂时先把元信息赋值给anonymousModuleMeta = meta。
然后触发onload,这时就会调用回调方法callback3,此回调方法就会修改当前回调模块(a.js)的状态值,将其设置为 module.status = STATUS.FETCHED。
再接下来 ,将统一 执行回调队列 callbackList 中的 a.js所对应的回调,也就是onFetched。
onFetched方法会检查a模块是否有依赖模块,因为a依赖于b,所以对模块a所依赖的b.js 执行_load()。
会去下载b模块,这时会先执行jquery的define方法。因为jquery没依赖模块,所以onload回调后。onFetched调用cb方法。
当b按照a一样的过程实现后,就会下载c模块。最终c,b,a模块都下载执行define,并onload结束后,也会调用cb方法,(先c,再b,后c)
所有模块都为ready之后,就会调用callback2方法。
最终回调到callback2,执行a和jquery模块的_compile方法:
首先编译a.js模块,模块a的function执行,因为a里面有require(b.js),因此会去执行b模块的function.
模块 a 的function开始执行
模块 b 的function开始执行
模块 c 的function开始执行
模块 c 的function执行完毕
模块 b 的function执行完毕
模块 a 的function执行完毕
最后执行jquery的function。
编译结束后,就执行callback1,就可以使用a和jquery对象了。
PS:seajs版本已经更新,现在没有_compile方法了。(大家自行去看,我也要去看下)
接着讲下seajs的模块编译_compile过程。
首先是a.js的编译
复制代码 代码如下: