RequireJS实例教程及命名冲突解决

require.js是一个遵循AMD规范,可以实现.js文件按需分块加载的前端框架。举个例子,我们在写前端代码时,常常会看到如下的写法:

<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="4.js"></script>
这段代码依次加载多个js文件,这样的写法有很大的缺点。首先,加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面),依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。使用 require.js框架即可彻底解决这种难题。

我们可以去官网下载require.js,使用该框架,在我们的html页面中常常如下引入:

<script src="js/libs/require.js" defer async="true" data-main="js/main"></script>
async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。data-main则表示我们自己的代码主文件所在路径。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。

main.js作为require.js第一个引入的js文件,自然要遵循一定的写法规范。首先,require.js主要目的是支持js按需分块加载,所以第一步是把相关的js文件按模块引入,写法如下:

//模块的配置
requirejs.config({
	baseUrl: "./",
	paths: {
		"jquery": "js/libs/jquery-1.8.0",
		"common": "js/libs/common",
		"countObject": "js/core/countObject",
		"dependCount": "js/core/dependCount",
		"countFunction": "js/core/countFunction"
	}
});
其中,baseUrl表示main.js目录的相对目录,依据相对目录规则可知"./"表示当前引入文件基目录与main.js在同一目录层级下;paths表示各个引入js文件在以baseUrl为基目录的基础上的详细目录地址。已jquery为例:jquery的引用目录是"./js/libs/jquery-1.8.0"。

当前Demo的目录结构如图所示:

(注)此步requirejs.config引用模块中,虽指出了各个js所在路径,但实际上并没有加载进来,实际加载进来是在接下来的模块引用代码中生效。

在上一步中js文件的引用配置已经配好了,接下来就是对所需的模块进行加载。模块加载的代码如下:

//应用程序
requirejs(['_main_']);
define("_main_", ["jquery", "common", "countObject", "countFunction", "dependCount"], function($, common, countObject, countFunction, dependCount) {
	//your code
});
模块使用define()函数来定义,上面代码中define("_main_",.......)表示将main.js定义为名称是"_main_"的模块,requirejs(['_main_']);则表示引用该模块。 这种定义模块名称的写法常常用在1对1的关系中,即1个html文件相对应1个主js文件,如demo中的index.html中的data-main="js/main"相对应的1个js文件是main.js。其他自定义模块引用如后面将介绍到的countObject.js,定义时无需定义模块名称,用define(function() {});即可。

define(...,[?],....)中[?]是一个字符串数组,字符串值为requirejs.config配置中paths的属性值,根据实际需要引入main.js中所需的模块,define(...,...,function(?,?,?){});中的function(?,?,?){}表示这些模块的外部调用名称,正常情况下与引入模块名称一致。

解决了模块的引用和加载,接下来就是这些模块的在代码中如何使用了。如对jquery模块的引用,由于该模块定义的外部名称是$,所以在使用时按照jquery的习惯使用$即可调用,其他模块调用大致相同,如countObject.add(1,1),表示送出1加1的结果。接下来主要讲讲countObject、countFunction和dependCount这三种常用的自定义模块的写法。

第一种是没有依赖于任何其他模块的自定义模块,如本Demo中的countObject

//非依赖对象定义
define(function() {
	var module = {};

	module.value = 0;

	//加法
	var add = function(a, b) {
		return a + b;
	}

	//减法
	var minus = function(a, b) {
		return a - b;
	}

	module.add = add;
	module.minus = minus;
	return module;
});
第二种是有依赖于其他模块的自定义模块,如dependCount:
//依赖对象定义
define(['./countObject'], function(countObject) {
	var module = {};

	//加法
	var add = countObject.add;

	//减法
	var minus = countObject.minus;

	module.add = add;
	module.minus = minus;
	return module;
});
这两种模块的使用方法都是通过“.“的来引用,如countObject.add(1,1)。

还有一种写法是用过new Object()的方法来引用,这类模块的写法如下:

define(function() {
	var target = null;

	function countTool() {
		target = this;
		target.value = 0;
	};

	countTool.prototype.add = function(a, b) {
		return a + b;
	};

	countTool.prototype.minus = function(a, b) {
		return a - b;
	};

	return countTool;
});
使用方法是:
var c = new countFunction();
var r = c.add(1,1);
console.log(r); // 2
理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合。那么,require.js是否能够加载非规范的模块呢?回答是可以的,在配置项时使用shim即可。不符合AMD规范的第三方库常见的有两种写法:第一种写法是

//dateUtil.js
(function(window) {
	var DateUtils = {};
	DateUtils.toString = function() {
		alert("toString");
	};
	// 全局变量
	window.DateUtils = DateUtils;
})(window);
另一种写法是:

//stringUtil.js
var StringUtils = {};
StringUtils.toUpperCase = function(input) {
	alert("toUpperCase");
}
要引用这两种脚本,可以使用如下代码:

//模块的配置
requirejs.config({
	baseUrl: "./",
	paths: {
		"jquery": "js/libs/jquery-1.8.0",
		"common": "js/libs/common",
		"countObject": "js/core/countObject",
		"dependCount": "js/core/dependCount",
		"countFunction": "js/core/countFunction",
		"dateUtil": "js/core/dateUtil",
		"stringUtil": "js/core/stringUtil"
	},
	shim: {
		dateUtil: {
			deps: [],
			exports: 'DateUtils'
		},
		stringUtil: {
			deps: [],
			exports: 'StringUtils'
		}
	}
});

//应用程序
requirejs(['_main_']);
define("_main_", ["jquery", "common", "countObject", "countFunction", "dependCount", "dateUtil", "stringUtil"], function($, common, countObject, countFunction, dependCount, dateUtil, stringUtil) {
	//your code
	stringUtil.toUpperCase();
	dateUtil.toString();

	window.StringUtils.toUpperCase();
	window.DateUtils.toString();
});
shim中deps表示该js的依赖项,如依赖于jquery,则为deps: [jquery],没有依赖则为空数组。第二个参数exports表示该js对外应用时的名称,即js中的对外应用的全局变量,如dateUtil.js中的DateUtils。
在实际应用中,还有一类第三方库的情况,它自身也定义了一个require,如下图所示psd.js库


这样的库必然会与require.js中的require相冲突,这时想要在require.js框架中使用这类自带require函数的第三方库,怎么办呢?首先,可以在使用psd.js库前,把已有的require.js框架全局变量保存下来,然后将psd.js动态加载进来,使用完成后,在对require.js框架全局变量进行重置。

//使用前
var _define = null;
var _requirejs = null;
var _require = null;
_define = window.define;
_requirejs = window.requirejs;
_require = window.require;
window.requirejs = null;
window.require = null;
window.define = null;

//加载psd.js
loadFiles([url + '/psd.js'
], function() {
	//使用psd.js
	//some code
	
	//使用后
	window.define = _define;
	window.requirejs = _requirejs;
	window.require = _require;
});

// 动态加载js文件
function loadFiles(urlArrValue, callback) {
	var staticPath = "";
	var urlArr = urlArrValue;
	var filesNum = urlArr.length;
	var loadedCount = 0;
	if(filesNum > 0) {
		var url = staticPath + urlArr[loadedCount];
		Load(url);
	}

	function Load(url) {
		var f;
		if(url.indexOf(".css") > 0) {
			f = document.createElement("link");
			f.type = 'text/css';
			f.rel = "stylesheet";
			f.href = url;
		} else {
			f = document.createElement("script");
			f.type = "text/javascript";
			f.src = url;
		}
		f.onload = function(e) {
			loadedCount++;
			if(loadedCount < filesNum) {
				var url = staticPath + urlArr[loadedCount];
				Load(url);
			} else {
				callback();
			}
		}
		f.onerror = function(e) {
			loadedCount++;
			if(loadedCount < filesNum) {
				var url = staticPath + urlArr[loadedCount];
				Load(url);
			} else {
				callback();
			}
		}
		document.head.appendChild(f);
	}
}

实例Demo下载地址:http://download.csdn.net/detail/zeping891103/9885475

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值