通过前面几步,我们基本实现了一个模块化编程,现在要为程序实现AMD的接口(define方法)
AMD的规范只定义了一个函数 “define”,它是全局变量。函数的描述为:
define(id?, dependencies?, factory);
具体请参考 –> Amd规范
实现AMD的类库两个比较著名的分别是RequireJS 和 CurlJS
说实话如果直接看这两个类库的源码,可能多少有点难,甚至懵逼,建议初学者可以参考别的实现:foio.github.io
我们把每一个模块改为一个js文件,然后实现我们的AMD模块加载器
add.js
1 2 3 4 5
| define([],function () { return function () { console.log("define an add module ...."); } });
|
minus.js
1 2 3 4 5
| define([],function () { return function () { console.log("define minus module ...."); } });
|
calc.js
1 2 3 4 5 6
| define(['./add','./minus'],function (add,minus) { return { add: add, minus: minus } });
|
main.js
1 2 3 4 5 6 7 8 9 10
| require(['./calc'],function (calc) { var btnAddEl = document.getElementById('btnAdd'); var btnMinusEl = document.getElementById('btnMinus'); btnAddEl.addEventListener("click",function () { calc.add(); }); btnMinusEl.addEventListener("click",function () { calc.minus(); }); });
|
通过分析,可以整个过程看做是一个”栈”操作.
- 1.define() 操作定义一个Module,立即压入”栈”(这里push到数组中);
- 2.加载该模块的deps(依赖数组)
- 3.出”栈”执行模块的工厂函数,获取返回值
define 函数
1 2 3 4 5 6 7 8 9 10 11 12 13
| function define(id,deps,length){ var len = arguments.length; if (len == 2) { factory = deps; deps = id; id = undefined; } var mod = new Module(id,deps,factory); context.newModules.push(mod); context.waitingModules.push(mod); mod.loadDeps(); exec(); }
|
exec函数(执行context.waitingModules中的模块,如果已经准备好,则从数组中剔除)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| * 执行所有等待模块,如果模块加载完成,则从等待数组剔除 * @return {[type]} [description] */ function exec() { var i; var j = 0; var depID; var len = context.waitingModules.length; var val; var mod; var args; var callback; for(i = len;i--;){ mod = context.waitingModules[i]; if ((!mod.returnVal) && mod.checkDeps()) { context.waitingModules.splice(i,1); args = []; callback = mod.factory; for(j = mod.deps.length;j--;){ depID = mod.deps[j]; args.unshift(mod.getDepsValue(depID)); } val = callback.apply(global,args); mod.returnVal = val; } } }
|
require函数其实也是一个define函数的过程,为了便于理解,暂时不处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| * 定义require函数 * @param {[type]} deps [description] * @param {Function} callback [description] * @return {[type]} [description] */ function require(deps, callback) { var mod = new Module(context.topModule,deps,callback); context.loads[context.topModule] = true; context.modulesMap[context.topModule] = mod; context.newModules.push(mod); context.waitingModules.push(mod); mod.loadDeps(); exec(); }
|
具体实现可以参考我的github或者foio.github.io实现.