JS模块加载

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>
发布了49 篇原创文章 · 获赞 8 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/wsliangjian/article/details/48471251