RequireJs用的是AMD规范,可以异步加载模块,解决了模块依赖,页面阻塞等问题,使用脚本时以module ID替代URL地址
<script src="js/require.js">script>
可以把上句代码放在body底部,或添加属性async="true"
来异步加载,async是html5属性,对于老式浏览器可以用defer,所以可以写成:
<script src="js/require.js" defer async="true">script>
可以给script添加data-main属性,require.js加载完成后会加载data-main属性值得文件,相当于入口文件,所以可写成如下:
<script src="js/require.js" defer async="true" data-main="js/main">script>
RequireJS默认假定所有的依赖资源都是js脚本,因此无需在module ID上再加”.js”后缀
通过define函数加载模块,确保了依赖关系,同时无需创建全局变量,有五种方式定义模块
如果一个模块仅含值对,没有任何依赖,则在define()中定义这些值对就好了:
define({
color: "black",
size: "unisize"
});
如果一个模块没有任何依赖,但需要一个做setup工作的函数,则在define()中定义该函数,并将其传给define():
define(function () {
//Do setup work here
return {
color: "black",
size: "unisize"
}
});
返回值可以是函数、数组或基本数据类型。
如果模块存在依赖:则第一个参数是依赖的名称数组;第二个参数是函数,在模块的所有依赖加载完毕后,该函数会被调用来定义该模块,
因此该模块应该返回一个定义了本模块的object。依赖关系会以参数的形式注入到该函数上,参数列表与依赖名称列表一一对应。
define(["./a", "./b"], function(a, b) {
return {
value: 1,
get: function() {
return a.foo(this.value) + b.bar(this.value);
}
}
});
模块函数以参数”a”及”b”使用这两个以”./a”及”./b”名称指定的模块。在这两个模块加载完毕之前,模块函数不会被调用。返回的对象作为一个新的模块,并且不作为全局变量存在。
可以在define()中包含了一个模块名称作为首个参数:
define("foo", ["a", "b"], function(a, b) {
//Define foo object in here.
});
这些常由优化工具生成。也可以自己显式指定模块名称,但这使模块更不具备移植性——就是说若将文件移动到其他目录下,就得重命名。一般最好避免对模块硬编码,而是交给优化工具去生成。优化工具需要生成模块名以将多个模块打成一个包,加快到浏览器的载人速度。
定义具名模块,通过require加载模块名称需一致,可以加载其它文件定义的具名模块,这时需通过path配置路径,定义具名模块并不会立即加载依赖的模块,仅在require时才回去加载依赖,所以在同一个文件下,可以先定义好模块之后再加载。
如果现有一些以CommonJS模块格式编写的代码,而这些代码难于使用上述依赖名称数组参数的形式来重构,可以考虑直接将这些依赖对应到一些本地变量中进行使用。可以使用一个CommonJS的简单包装来实现:
define(function(require, exports, module) {
var a = require('a'),
b = require('b');
//Return the module value
return function () {};
});
该方法通过参数名识别模块,并且必须保证顺序,如果用压缩工具压缩,则不起作用,这是可以通过依赖引入模块:
define(["require", "exports", "module", "a", "b"], function(require, exports, module) {
var a = require('a'),
b = require('b');
//Return the module value
return function () {};
});
RequireJS以一个相对于baseUrl的地址来加载所有的代码,默认baseUrl为引入require.js的文件的路径,当有data-main属性时,baseUrl与该属性的目录一致,baseUrl亦可通过RequireJS config手动设置,如下所示:
requirejs.config({
baseUrl: 'js/lib',
});
配置函数一般写在main.js入口文件中,也可写在外头,但写在外头时,入口文件必须放在baseUrl指定的目录,否则无法加载。即如果这样写
<script src="js/require.js" defer async="true" data-main="main">script>
requirejs.config({
baseUrl: 'js/lib',
});
那么main.js必须放在js/lib目录下,所以通常最好把配置函数写在入口文件里,或者不要指定baseUrl。
基准目录确定后,可以设置path属性配置文件路径,假设文件目录如下
可如下配置
requirejs.config({
baseUrl: 'js/lib',
paths: {
app: '../app'
}
});
这样通过app即可定位到js/app目录。
有时候你想避开”baseUrl + paths”的解析过程,而是直接指定加载某一个目录下的脚本。此时可以这样做:如果一个module ID符合下述规则之一,其ID解析会避开常规的”baseUrl + paths”配置,而是直接将其加载为一个相对于当前HTML文档的脚本:
注意:本地加载时/指定的根目录为index.html所在的盘符,而不是其所在的目录
一般来说最好用相对路径,便于后期维护和管理。
对于以”.js” 结束,此时路径是相对于引入require.js的html文件,相当于requirejs对文件路径不做处理,与原生引入类似。
对于”/” 开始,如果通过path配置路径,后面可以不以.js结尾,如
requirejs.config({
baseUrl: 'js/lib',
paths: {
test: '/js/app/test'
}
reqiuirejs会自动补全.js,但如果直接用require()引入模块,则必须以.js结尾,如:
require('/js/app/test.js', function(){});
不同地方定义的path,会自动合并,但同名的路径后面后覆盖前面
为那些没有使用define()来声明依赖关系、设置模块的”浏览器全局变量注入”型脚本做依赖和导出配置。对于没有按require规范编写的库以及库的插件,可以用shim来配置,如下:
requirejs.config({
shim: {
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'underscore': {
exports: '_'
},
'foo': {
deps: ['bar'],
exports: 'Foo',
init: function (bar) {
return this.Foo.noConflict();
}
}
}
});
deps为依赖关系,exports的值为库引入的全局变量,init为库引入后的初始化函数,解决库命名的冲突问题。
那些仅作为jQuery或Backbone的插件存在而不导出任何模块变量的”模块”们,shim配置可简单设置为依赖数组:
requirejs.config({
shim: {
'jquery.colorize': ['jquery'],
'jquery.scroll': ['jquery'],
'backbone.layoutmanager': ['backbone']
}
});
在多处定义的shim会自动合并,所以可以创建全局的shim,然后根据不同项目配置不同shim
对于给定的模块前缀,使用一个不同的模块ID来加载该模块。
该手段对于某些大型项目很重要:如有两类模块需要使用不同版本的”foo”,但它们之间仍需要一定的协同。 在那些基于上下文的多版本实现中很难
做到这一点。而且,paths配置仅用于为模块ID设置root paths,而不是为了将一个模块ID映射到另一个。
示例:
requirejs.config({
map: {
'some/newmodule': {
'foo': 'foo1.2'
},
'some/oldmodule': {
'foo': 'foo1.0'
}
}
});
模块ID可以用*,表示对所有模块加载使用本配置。
常常需要将配置信息传给一个模块。这些配置往往是application级别的信息,需要一个手段将它们向下传递给模块。在RequireJS中,基于requirejs.config()的config配置项来实现。要获取这些信息的模块可以加载特殊的依赖“module”,并调用module.config()。示例:
requirejs.config({
config: {
'bar': {
size: 'large'
},
'baz': {
color: 'blue'
}
}
});
bar.js:
define(function (require, exports, module) {
var size = module.config().size;
});
baz.js:
define(['module'], function (module) {
var color = module.config().color;
});
require.s.contexts._.config
属性保存了require的配置信息。
如果想用require加载css等非js文件,就需要插件,加载插件用!作为前缀,如
define(['css!foo'], function (foo) {
return {};
});
则在加载foo模块前会加载css.js插件,css插件路径可以通过path配置,也可通过map配置,如:
requirejs.config({
map: {
*: {
'css': 'lib/css'
}
}
});