回首萧瑟,残月挂角,孤草弄影。
看了一下上一篇随笔的日期,距离上一篇日志又过去了许久。在这段时间中,我尽全力去拯救那间便利店,可惜到最后依然失败,这一次是所有的出路全部没有了,我也做了所有的努力。闲下来来了,补篇日志吧。
今天想写的是js中的AMD规范。AMD,即Asynchronous Module Definition的缩写,它是前端代码大爆炸后,为了更好的管理js代码所做出的一种努力。它来源于commonjs,一个野心勃勃的组织。发展至今已经为许多著名的js库所使用。我最先接触它是在使用nodejs+express+jade进行web编辑的时候,后来一时兴趣又接触到了dojo,再然后jquery也开始使用AMD来组织代码。昨天在翻看园子里面js的文章的时候,又看到Sea.js这个代码库,看了一下,它是AMD的一个实践,这也是我写这篇日志的起因。
AMD规范从名字来看,模块化和异步是他的核心。事物的发展是由需求驱动的,js的发展也一样。在前端的js大爆炸之后,js的代码量越来越大,问题也不断的出现—功能边界模糊,命名冲突,依赖混乱,代码冗余等等。AMD在功能模块话的基础上进化而来,用模块管理功能,用异步的方式加载模块。说了这么多,那么AMD的代码定义是什么呢?
define([module-name?], [array-of-dependencies?], [module-factory-or-object])
就是上面的一行API。很简单的一行,实现起来也不难。我自己就仿照这个造过一个木轮子,思路如下:
全局对象:$libs(object),require(function),模块函数块中要公开的对象全部悬挂于$libs上,使用require('module Name')获得接口;
核心对象:module(moduleName,refFunc,refModules);
js文件加载与通知(原生js,为了简单,没有使用addEventListener,使用=进行事件挂载)
createScripts:function(moduleName){
var sc = document.createElement("script");
sc.setAttribute("type", "text/javascript");
sc.src = setting.getModulePath(moduleName);
sc.onload = sc.onreadystatechange = this.reached;
sc.onerror = this.error;
document.body.appendChild(sc);
}
reached:function(event){
var node = event?event.target:window.event.srcElement;
if(!node.readyState || node.readyState == "loaded" || node.readyState == "complete"){
mfMatrix.update(setting.getModuleName(node.getAttribute("src")),"success");
node.onload = node.onreadystatechange = null;
node.parentNode.removeChild(node);
}
}
模块执行:executeModule(module),关键在于参数传入
function executeModule(module){ if(module.refModules.length == 0){ module.refFunc(); return; } var prs = []; var order = "module.refFunc("; for(var i = 0;i!=module.refModules.length;i++){ prs.push(eval("require('"+module.refModules[i]+"')")); order += "prs["+i+"]"; if(i < module.refModules.length - 1) paras+=','; } order +=")"; eval(order); }
上面也说了,这是一个木轮子,仅供参考,要想投入实用,还有一些细节要处理,比如模块名称与js文件名称的转换,js文件加载失败后的重新再次加载处理错误捕捉等等,都是应该考虑的问题。