打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
关于js模块加载的尝试

有了seajs、requireJ这样的模块加载框架,一直想研究,今天先尝试自己来写一下简单的加载功能,等了解后再去看大牛们的源码,仅当作为自己学习练习,有很多考虑不周的地方请指出,主要就两个方法:

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下载地址:点我点我点我

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
大白话理解Webpack!
致我们终将组件化的Web
seajs快速参考
第三篇 Arcgis api for js之dojo框架使用
jQuery实现拖动布局并将排序结果保存到数据库
In.js 一个轻量级的模块依赖关系管理库 ? 笨笨剥壳
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服