模块化:将复杂的系统分解为高内聚、低耦合的模块,使系统开发变得可控、可维护、可拓展,提高模块的复用率。
异步模块——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的基本原理是足够了的,希望对同学们模块化开发有帮助