Created
September 10, 2012 08:39
-
-
Save dexteryy/3689700 to your computer and use it in GitHub Desktop.
AMD -> module pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 这个define的实现会让amd模块声明变成传统的module pattern | |
function define(fullname, deps, block){ | |
if (!block) { | |
if (deps) { | |
block = deps; | |
} else { | |
block = fullname; | |
fullname = []; | |
} | |
if (typeof fullname !== 'string') { | |
deps = fullname; | |
fullname = ""; | |
} else { | |
deps = []; | |
} | |
} | |
var callee = define, | |
len = deps.length, | |
exports = {}, | |
opt = callee._global_exports[fullname] || {}, | |
current_ns = callee._current_ns = opt.ns | |
|| callee._current_ns || callee._ns || 'window'; | |
deps = ((/^function.*?\(([\w'"\/\-\:,\n\r\s]*)\)/ | |
.exec(block.toString()) || [])[1] || '') | |
.replace(/\s+/g, '').split(','); | |
deps.length = len; | |
var args = deps.map(function(name){ | |
return (window[current_ns] || {})[name]; | |
}); | |
args.push(function(reqs, callback){ | |
if (callback) { | |
require(reqs, callback); | |
} else { | |
return (callee._global_exports[reqs] || {}).exports; | |
} | |
}); | |
args.push(exports); | |
exports = opt.exports = block.apply(this, args) || exports; | |
if (opt.names) { | |
opt.names.forEach(function(name){ | |
name = name.split('.'); | |
var context = window, i = name[0]; | |
if (name[1]) { | |
context = context[i] = context[i] || {}; | |
i = name[1]; | |
} | |
context[i] = exports; | |
}); | |
} | |
callee._current_ns = null; | |
} | |
// require的实现跟define一样,不过是异步的 | |
function require(reqs){ | |
if (typeof reqs === 'string') { | |
reqs = [reqs]; | |
} | |
var args = arguments; | |
setTimeout(function(){ | |
define.apply(this, args); | |
}, 0); | |
} | |
define._global_exports = {}; | |
// 为模块设置命名空间,既可以避免产生全局变量, | |
// 也可以隔离不同体系的模块(比如'mod/event'和'jquery/event'),避免命名冲突 | |
define.ns = function(mid, namespace){ | |
if (!namespace) { | |
this._ns = mid; | |
} else { | |
var opt = this._global_exports; | |
if (!opt[mid]) { | |
opt[mid] = { | |
names: [] | |
}; | |
} | |
opt[mid].ns = namespace; | |
} | |
}; | |
// 将模块的exports映射到全局命名空间下,让没有封装到amd模块里的代码也可以使用 | |
define.config = function(mid, vars){ | |
if (typeof mid === 'object') { | |
for (var i in mid) { | |
this.config(i, mid[i]); | |
} | |
return; | |
} | |
var opt = this._global_exports; | |
if (!opt[mid]) { | |
opt[mid] = { | |
ns: this._ns, | |
names: [] | |
}; | |
} | |
if (typeof vars === 'string') { | |
vars = [vars]; | |
} | |
[].push.apply(opt[mid].names, vars); | |
}; | |
// 以下是DEMO | |
// 自定义默认命名空间,默认为window | |
define.ns('Ark'); | |
// 给模块单独定义命名空间,这个模块依赖的参数都会从这个命名空间下读取 | |
define.ns('B', 'Y'); | |
// 手工配置模块的exports在全局命名空间下的名称(一对多) | |
define.config('mod/dialog', '$.dialog'); | |
define.config('mod/dialog', ['Ark.dui_dialog', 'Ark.Dialog']); | |
define.config({ | |
'mod/lang': ['_', 'Ark._'], | |
'A': ['Ark.A', 'Y.A'], | |
'B': ['Ark.B', 'Y.B'] | |
}); | |
// 合并进来的 mod/lang.js,如果之前没有模块名,可在合并脚本执行的时候自动生成 | |
// 要用现成工具的话,可以先用ozma.js把所有amd模块合并为一个发布文件,再把这个发布文件用 @import 的方式合并到传统网页的js中 | |
define('mod/lang', function(require, exports){ | |
exports.isFunction = function(){}; | |
}); | |
// 合并进来的 mod/dialog.js | |
define('mod/dialog', ['mod/lang'], function(_, require, exports){ | |
console.info('mod/dialog running..'); | |
require('A', function(A){ | |
// 因为这里的require在模块内调用,所以这个函数会异步执行,参数A从mod/dialog的命名空间下读取(Ark.A) | |
console.info('require A: ', A); | |
}); | |
return function(str){ | |
// 只有一个参数的require会立刻执行,返回模块B的exports,不需要全局命名空间 | |
console.info(str, _, require('B')); | |
}; | |
}); | |
define('A', function(){ | |
return { name: 'A' }; | |
}); | |
// 因为模块B的命名空间是Y,所以这里的参数A取的是Y.A | |
define('B', ['A'], function(A){ | |
return { name: 'B', A: A }; | |
}); | |
Ark.dui_dialog('Dialog: '); | |
console.info('lang: ', _); | |
console.info('Ark: ', Ark); | |
console.info('Y: ', Y); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment