JS模块加载

来源:互联网 发布:vmware for ubuntu 32 编辑:程序博客网 时间:2024/04/29 21:09

VM.define(‘模块名称’,{url:‘模块路径’,requires:‘模块依赖项’(可以是模块名的字符串,或者数组)});  

VM.use(‘模块名称’,‘回调函数callback’);

一个是定义模块,一个是使用模块;使用的模块都必须先定义,

定义的时候不会加载模块,只有在使用的时候才加载模块;

1、不会出现重复加载的模块,调用过的模块不会再append第二次,不能定义相同名字的模块;

2、依赖项可以是多个,从左到右加载,多个的时候用数组传参,单个时可以用字符串传参;

3、支持链式调用,要避免循环依赖的情况;

代码如下:使用方法:只需引入myModule.js文件, <script type="text/javascript" src="myModule.js"></script>

(function() {// 调试提示var log = function(content) {if (typeof console.log === 'function') {console.log(content);} else {alert(content);}}var createScript = function(url) {var script = document.createElement('script');script.type = 'text/javascript';script.src = url;return script;};var head = document.getElementsByTagName('head')[0];var toString = Object.prototype.toString;var VModule = {};/** * 定义模块 * @param name {string} * @param options {object} url/requires */VModule.define = function(name, options) {// 定义模块名称、地址和依赖if (!this.modules)this.modules = {};if (this.modules[name]) {log(name + '已经存在,请更换名称.');return;}this.modules[name] = options;// 是否加载this.modules[name].isLoad = false;// 是否使用this.modules[name].isUse = false;// 回调队列this.modules[name].callBackQueue = [];log(this.modules);return this;}VModule.use = function(name, func) {var len, self = this;if (!this.modules[name]) {log(name + '不存在.');return this;}// 回调队列,用于多次use同一个模块时的多个回调var callBackQueue = this.modules[name].callBackQueue;if (!this.modules[name].isUse) {// 标记模块已经使用过this.modules[name].isUse = true;// 推入队列callBackQueue.push(func);var url = this.modules[name].url;var requires = this.modules[name].requires;// 串行依赖情况if (toString.call(requires) == '[object String]') {this.use(requires, function() {self.load(name, callBackQueue);});return this;}// 并行依赖处理if (toString.call(requires) == '[object Array]') {// 循环查找len = requires.length;this.modules[name].count = len;for (var i = 0; i < len; i++) {var self = this;this.use(requires[i], function() {VModule.modules[name].count--;// 串行依赖即等待所有的文件加载完毕后才执行回调if (VModule.modules[name].count == 0) {self.load(name, callBackQueue);}})}return this;}this.load(name, callBackQueue);} else {// 如果模块已经标记使用,但是模块还未下载完毕时,加入队列, 如果下载完毕则直接执行回调函数if (!this.modules[name].isLoad) {func && callBackQueue.push(func);} else {func && func();}return this;}}VModule.load = function(name, callBackQueue) {if (!this.modules[name].isLoad) {var self = this;var script = createScript(self.modules[name].url);script.onload = script.onreadystatechange = function() {if ((!this.readyState) || this.readyState === "loaded"|| this.readyState === "complete") {self.modules[name].isLoad = true;// 循环调用回调队列for (var i = 0, n = callBackQueue.length; i < n; i++) {callBackQueue[i]();}}}head.appendChild(script);}}window.VM = VModule;})();
测试demo:

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>js模块化</title><script type="text/javascript" src="myModule.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>

0 0
原创粉丝点击