关于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测试数据/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://HdhCmsTestcnblogs测试数据/NNUF/
分类: JS , 实例 , 原创
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息