关于js模块加载的尝试
关于js模块加载的尝试
看了sea.js、requireJs那么完善的模块加载框架,今天尝试来自己写一下简单的加载功能,仅当作为自己学习练习,有很多考虑不周的地方请指出,主要就两个方法:
VM.define(‘模块名称’,{url:‘模块路径’,requires:‘模块依赖项’(可以是模块名的字符串,或者数组)});
VM.use(‘模块名称’,‘回调函数callback’);
一个是定义模块,一个是使用模块;使用的模块都必须先定义,
定义的时候不会加载模块,只有在使用的时候才加载模块;
1、不会出现重复加载的模块,调用过的模块不会再append第二次,不能定义相同名字的模块;
2、依赖项可以是多个,从左到右加载,多个的时候用数组传参,单个时可以用字符串传参;
3、支持链式调用,要避免循环依赖的情况;
修改:上次的代码存在考虑不周的情况,多谢园友 程序猿小卡 留言的指出,现再的也可能有问题,但是如果正常使用依赖,相信还是能够满足的,仅供研究:)
代码如下: 使用方法:只需引入myModule.js文件, <script type="text/javascript" src="myModule.js"></script>
myModule.js代码如下:
1 /* * 2 3 * Author : vvg 4 5 * version : 0.1.1 6 7 * name : VModule.js 8 9 * */ 10 11 ( function () { 12 // 调试提示 13 var log = function (content) { 14 if ( typeof console.log === 'function' ) { 15 console.log(content); 16 } else { 17 alert(content); 18 } 19 } 20 21 var createScript = function (url) { 22 var script = document.createElement('script' ); 23 script.type = 'text/javascript' ; 24 script.src = url; 25 return script; 26 }; 27 28 var head = document.getElementsByTagName('head')[0 ]; 29 var toString = Object.prototype.toString; 30 31 var VModule = {}; 32 /* * 33 * 定义模块 34 * @param name {string} 35 * @param options {object} url/requires 36 */ 37 VModule.define = function (name, options) { 38 // 定义模块名称、地址和依赖 39 if (! this .modules) this .modules = {}; 40 if ( this .modules[name]) { 41 log(name + '已经存在,请更换名称.' ); 42 return ; 43 } 44 this .modules[name] = options; 45 // 是否加载 46 this .modules[name].isLoad = false ; 47 // 是否使用 48 this .modules[name].isUse = false ; 49 // 回调队列 50 this .modules[name].callBackQueue = []; 51 return this ; 52 } 53 54 VModule.use = function (name, func) { 55 var len, self = this ; 56 if (! this .modules[name]) { 57 log(name + '不存在.' ); 58 return this ; 59 } 60 // 回调队列,用于多次use同一个模块时的多个回调 61 var callBackQueue = this .modules[name].callBackQueue; 62 if (! this .modules[name].isUse) { 63 // 标记模块已经使用过 64 this .modules[name].isUse = true ; 65 // 推入队列 66 callBackQueue.push(func); 67 var url = this .modules[name].url; 68 var requires = this .modules[name].requires; 69 70 // 串行依赖情况 71 if (toString.call(requires) == '[object String]' ) { 72 this .use(requires, function () { 73 self.load(name, callBackQueue); 74 }); 75 return this ; 76 } 77 78 // 并行依赖处理 79 if (toString.call(requires) == '[object Array]' ) { 80 // 循环查找 81 len = requires.length; 82 this .modules[name].count = len; 83 for ( var i = 0; i < len; i++ ) { 84 var self = this ; 85 this .use(requires[i], function () { 86 VModule.modules[name].count-- ; 87 // 串行依赖即等待所有的文件加载完毕后才执行回调 88 if (VModule.modules[name].count == 0 ) { 89 self.load(name,callBackQueue); 90 } 91 }) 92 } 93 return this ; 94 } 95 this .load(name, callBackQueue); 96 } else { 97 // 如果模块已经标记使用,但是模块还未下载完毕时,加入队列, 如果下载完毕则直接执行回调函数 98 if (! this .modules[name].isLoad){ 99 func && callBackQueue.push(func); 100 } else { 101 func && func(); 102 } 103 return this ; 104 } 105 } 106 VModule.load = function (name, callBackQueue) { 107 if (! this .modules[name].isLoad) { 108 var self = this ; 109 var script = createScript(self.modules[name].url); 110 script.onload = script.onreadystatechange = function () { 111 if ((! this .readyState) || this .readyState === "loaded" || this .readyState === "complete" ) { 112 self.modules[name].isLoad = true ; 113 // 循环调用回调队列 114 for ( var i = 0, n = callBackQueue.length;i<n;i++ ){ 115 callBackQueue[i](); 116 } 117 } 118 } 119 head.appendChild(script); 120 } 121 } 122 123 window.VM = VModule; 124 125 })();
我的测试DEMO:
<! DOCTYPE html > < html > < head > < meta charset ="utf-8" /> < title > js模块化 </ title > < script type ="text/javascript" src ="Module.js" ></ script > </ head > < body > < p id ="jq" > 测试 </ p > < p id ="jq2" > 测试 </ p > < script type ="text/javascript" > VM.define( ' a ' , {url: ' moduleA.js ' , requires:[ ' b ' , ' d ' , ' c ' ]}) .define( ' b ' , {url: ' moduleB.js ' }) .define( ' c ' , {url: ' http://common.cnblogs.com/script/jquery.js?178979879891 ' }) .define( ' d ' , {url: ' moduleD.js ' , requires:[ ' e ' , ' g ' , ' f ' ]}) .define( ' e ' , {url: ' moduleE.js ' , requires: ' f ' }) .define( ' f ' , {url: ' moduleF.js ' }).define( ' g ' , {url: ' moduleG.js ' }); VM.use( ' a ' , function () { $( ' #jq ' ).html( ' JQ下载成功!! ' ).css( ' color ' , ' red ' ); }).use( ' a ' , function () { $( ' #jq2 ' ).html( ' JQ下载成功!! ' ).css( ' color ' , ' red ' ); }).use( ' a ' , function (){ $( ' #jq2 ' ).append( ' <em>第三次加载</em> ' ).find( ' em ' ).css( ' color ' , ' blue ' ); }).use( ' f ' , function (){ console.log( ' F加载成功! ' ); }) </ script > </ body > </ html >
DEMO下载地址: 点我点我点我
转载请注明出处: http://www.cnblogs.com/NNUF/
分类: JS , 实例 , 原创
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息