关于Require的使用
因为 javascript 天生的缺点,语言本身没有集成命名空间的概念,所以变量名、函数名很容易发生冲突。大家想尽了各种办法,给 js 添加命名空间的概念,其中最成熟的套路,就是 RequireJS 这种。
总之,RequireJS 定义了(define)一个命名空间,在定义的时候,顺便引用了需要使用其他命名空间。我们注意到,按照 RequireJS 的术语,它把命名空间叫做“模块”。注意,在这里,RequireJS 定义的模块(命名空间)是匿名的,没有取名,这是和c#不同的地方。
但这个不要紧,因为其他 js 在用到你这个 js 的时候,一般是根据文件名称加载的,同时可以通过上面的 xx 这种方式,给模块(命名空间)自定义别名,所以,取不取名,还真不是关键。
Require配置
页面中要加载require.js并指明主要入口文件。
<!--data-main="main",等号右边的main指的main.js,相当于入口-->
<script type="text/javascript" data-main="<%=path%>/lib/main" src="<%=path%>/lib/require.js"></script>
对于入口文件中作如下设置:
require.config({
urlArgs : "timestamp=" + (new Date()).getTime(),
waitSeconds: 60,
paths : {
// 省略.......
userModel:"modules/userModel",
userCollection:"modules/userCollection"
},
shim : {
bootstrap : {
deps : [ "jquery" ],
exports : "$.fn.popover"
},
bootstrap_datetimepicker : {
deps : [ "jquery", "bootstrap" ],
exports : "$.fn.datetimepicker"
},
jqueryIfrmdailog : {
deps : [ "jquery" ],
exports : "$.ShowIfrmDailog"
},
}
});
var requirArray = ["jquery", "jqueryUI"];
require(requirArray, function($, jqueryUI) {
//
});
参数说明:
baseUrl: 查找所有模块的根路径。
urlArgs :RequireJS 用来匹配资源的额外的URL的查询参数 。通常的用法是在浏览器或者服务器配置不对的时候禁用缓存。
waitSeconds: 放弃加载脚本前的等待的秒数。 设置为 0 则禁用此功能。默认是 7 秒。
paths: 映射到不能直接在baseUrl下找到的模块名。 通常, path设置的路径是相对于baseUrl 的,除非 以 “/“ 开头或包含URL协议 (例如” http:”)。path的设置不要加.js后缀,因为path也可能是映射到一个目录。 如果path映射的是一个模块,RequireJS会自动加上.js后缀。
shim: 为那些没有使用define() 声明依赖项、没有设置模块值、老的、传统的”浏览器全局”脚本配置依赖项和exports。
map: 对于给定的相同的模块名,加载不同的模块,而不是加载相同的模块。
config: 传递一个配置信息到模块中是一个常见的需求。这个配置信息通常是应用的一部分,我们需要把它传递到模块中。 在 RequireJS 中,requirejs.config()中的config配置项 就是为了解决这个需求。 模块中可以通过内置依赖模块”module” ,通过调用module.config()方法来获取传递进来的配置信息.
packages: 配置从CommonJS 包来加载模块.
context: 加载上下文配置(require.config的对象)的名字。 只要顶级 require调用指定一个唯一context字符串,require.js就可以在一个页面中加载多个版本的模块。
deps: 需要加载的依赖项的数组。当在require.js加载前使用全局 require对象来定义配置的时候很有用,也可以在require()一定义后就马上加载指定依赖项的时候用。
callback: 所有依赖项加载后执行的回调函数。
enforceDefine: 如果设置为true, 当加载的脚本是没用define()包装过,且在shim配置中没有配置exports值时会抛错。
xhtml: 如果设置为 true,requireJS 将使用document.createElementNS() 来创建script标签。
scriptType: 设置 RequireJS生成的 script 标签的 type属性值。默认是”text/javascript”。
require关键字就是一个加载方法,加载的时候,可以定义别名;除了这种方法外,还可以用define,define是你定义自己的模块的时候使用,可以顺便加载其他的js。
define定义模块
define(["jquery"], function($){
var util = {};
util._helper = {};
// 日期格式化输出
util._helper.dateFormat = function(date , fmt) { //author: meizz
if (date == null || ! (date instanceof Date)) {
return "";
}
var o = {
"M+" : date.getMonth() + 1, //月份
"d+" : date.getDate(), //日
"h+" : date.getHours(), //小时
"m+" : date.getMinutes(), //分
"s+" : date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth() + 3) / 3), //季度
"S" : date.getMilliseconds()
//毫秒
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "")
.substr(4 - RegExp.$1.length));
for ( var k in o)
if (o.hasOwnProperty(k) && new RegExp("(" + k + ")").test(fmt))
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
};
return util;
});
其他
路径与后缀名
在 require 一个 js 文件的时候,一般不需要加上后缀名。如果加上后缀名,会按照绝对路径加载。没有后缀名,是按照下面的路径加载:
也就是默认加载 data-main 指定的目录,即 js/main.js 文件所在的目录。当然,你可以通过配置文件修改。
- define 定义模块方法只能用在独立的js文件中,不能在页面中直接使用。
否则会报 Mismatched anonymous define() module 错误。
和其他第三方js类库是否冲突?
不会冲突。一般比较规范的类库,都会给自己的js加上命名空间。比如 wojilu 旧有的 wojilu.common.js ,其实就是放在 wojilu 命名空间中(当然是通过更原始的方式实现命名空间的)。
在通过 RequireJS 加载这些第三方的 js 的时候,完全不要有任何担忧。
当然,如果第三方类库能够使用 RequireJS 的方式进行改造,那是最好。比如 wojilu 中大多数js 都按照 RequireJS 的方式进行了改造。但是,如果你不改造,也是完全不要紧的。
在代码中 require 一个文件多次,是否会导致浏览器反复加载?
不会,这是 RequrieJS 的优点,即使你反复 require 它,它只加载一次。