模块化:将复杂的系统分解为高内聚、低耦合的模块,使系统开发变得可控、可维护、可拓展,提高模块的复用率。
异步模块——AMD:请求发出后,继续其他业务逻辑,知道模块加载完城执行后续的逻辑,实现模块开发中对模块加载完成后的引用。
优点有很多,比如:
1:懒加载,提高网站性能
2:功能模块化
3:解决命名冲突
4:...
参考require.js,那么我们来实现一个简单的amd库,主要有三个模块方法
1.config——配置模块路径
2.define——定义模块方法
3.require——模块入口方法
以下是实现学习版的基本函数
;
(function(win) {
win.config = {}; //路径配置
var cache = {}, //模块缓存
require = function(deps, callback) {//模块入口方法,deps,依赖模块
count = 0, //未加载的模块计数器
},
define = function(url, callback) {}, //定义模块方法
loadModule = function(url, callback) {}, //模块加载方法
loadDone = function(params, callback){},//所有模块加载完毕
loadSript = function(url) {}; //加载js文件
win.require = require;
win.define = define;
})(window);
同时我们新建三个js文件,皆为同一个路径,分别为demo.js,demo1.js,demo2.js
//demo1.js文件内容
define('demo1',function(){
return {
a: 1
}
})
//demo2.js文件内容
define('demo2',function(){
return {
b: 2
}
})
//demo.js
window.config = {
demo1: './demo1.js',
demo2: './demo2.js'
}
require(['demo1', 'demo2'], function(demo1, demo2) {
console.log(demo1)
console.log(demo2)
})
上面看起来很像是require.js的写法吧!想必看了上面的代码就知道这个代码的意思,现在来让我们实现它吧!
require = function(deps, callback) { //模块入口方法
/*url:需要加载的文件,deps,依赖模块*/
var i = 0,
params = [],
count = 0; //未加载的模块计数器
for (; i < deps.length; i++) {
count++;
(function(index) { //闭包保存i值
loadModule(deps[index], function(module) {
count--
params[index] = module
if (count == 0) {//为0则所有模块加载完毕
loadDone(params, callback)
}
})
})(i);
}
},
define = function(url, callback) { //定义模块方法
cache[url].export = callback() //缓存
cache[url].onload(cache[url].export) //执行回调
},
loadModule = function(url, callback) { //模块加载方法
if (!cache[url]) { //如果不存在模块则加载并缓存
cache[url] = {
onload: callback,
export: null
};
loadSript(config[url])
} else {//否则直接从缓存中输出
callback(cache[url].export)
}
},
loadDone = function(params, callback) { //所有模块加载完毕
callback.apply(null, params)
},
loadSript = function(url) { //加载js文件
var script = document.createElement('script');
script.async = true;
script.type = 'text/javascript';
script.src = url
script.charset = 'UTF-8';
document.querySelector('body').appendChild(script)
};
<script src="requireDemo.js"></script>
<script src="demo.js"></script>
requireDemo.js就是我们写的demo版本的amd的库,运行demo.js,看看log出现什么
但是以上代码还存在许多问题,如:
没有处理参数,字符串
没有处理循环依赖问题
没有处理CMD写法
没有处理js文件加载状态
define一个模块显示的声明id,应该可以忽略显示的声明id,如define(function(){}),有兴趣的同学可以参考司徒的文章getCurrentScript获得当前js执行文件名称
还有其他许多问题,但是对我们理解amd的基本原理是足够了的,希望对同学们模块化开发有帮助