Requirejs简介
AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。RequireJS就是AMD规范最好的实现者之一。使用RequireJS有以下几点优势:
避免命名冲突,闭包,匿名自执行函数, 模块化只向外面暴露该模块的接口。
更好的分离。一堆script脚本,html中只需引入一个主入口就好了。然后在依赖进来。
更好的组织代码,大型项目的维护,多人开发,代码风格不一样,业务逻辑混杂,一个文件一个模块。单一职责原则,体现OOP思想。
更好的依赖管理,可以很好的维护各个模块之间的依赖关系。
按需加载,需要什么功能就加载什么模块。
防止js加载阻塞页面渲染。 Requirejs是异步加载的,可防止Js中有alert()阻塞页面渲染;
主入口data-main
require.js 在加载的时候会检察data-main 属性,将data-main 属性的js文件作为主入口进行加载:
<script data-main="scripts/main" src="scripts/require.js"></script>
这时会将main.js文件作为主要入口,通过main.js文档中设置其他的脚本进行加载,由于requirejs默认加载的js文档,因此可以省略main.js的后缀,直接写成main。需要注意的是main中的脚本是异步加载的。所以如果你在页面中配置了其它JS加载,则不能保证它们所依赖的JS已经加载成功。
例如:
<script data-main="scripts/main" src="scripts/require.js"></script>
<script src="scripts/other.js"></script>
如果other.js有依赖到main中设置加载的a.js文件,则不能保证加载other.js时a.js已经加载完成。
路径设置
RequireJS以一个相对于baseUrl的地址来加载所有的代码。 页面顶层<script>
标签含有一个特殊的属性data-main,require.js使用它来启动脚本加载过程,而baseUrl默认与该属性相一致的目录。
当然我们也可以在主入口main文档中通过require.config来设置,我们通常需要用到require.config来设置的有(1)baseUrl;(2)paths;
先看第一个例子:
文档结构如下:
www/
• index.html
• js/
• app/
• sub.js
• lib/
• jquery.js
• canvas.js
• app.js
• main.js
main.js设置如下:
requirejs.config({
baseUrl: 'js/lib',
paths: {
app: '../app'
}
});
requirejs(['jquery', 'canvas', 'app/sub'],
function ($,cv, sb) {
// jQuery, canvas and the app/sub module are all
// loaded and can be used here now.
});
baseUrl设置为js/lib,因此下面的paths设置的路径都是相对于上面的baseUrl的相对路径,当然也可以写绝对路径。这里需要的是这里的 app: ‘../app’ 没有加js后缀,因此可以是js文件,也可以是一个路径。
上面例子中的callback函数中发现有$参数,这个就是依赖的jquery模块的输出变量,cv, sb 分别对应。
第二个例子:
require.config({
paths : {
jquery : ["http://libs.baidu.com/jquery/2.0.3/jquery", " jquery-1.10.2"],
jqueryUI : " http://code.jquery.com/ui/1.10.4/jquery-ui"
}
})
通过paths的配置会使我们的模块名字更精炼,paths还有一个重要的功能,就是可以配置多个路径,如果远程cdn库没有加载成功,可以加载本地的库。
定义模块
模块不同于传统的脚本文件,它良好地定义了一个作用域来避免全局名称空间污染。它可以显式地列出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入,而无需引用全局变量。
Requirejs 通过define来定义一个模块,我们常用到定义模块的方式有两种:一种是没有其他依赖,另外一种是依赖其他模块。
1、没有其他依赖
如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。假定现在有一个add.js文件,它定义了一个add模块。那么,add.js就要这样写:
// add.js
define(function (){
var add = function (x,y){
return x+y;
};
return {
result: add
};
});
2、存在其他依赖
如果模块存在依赖:则第一个参数是依赖的名称数组;第二个参数是函数,该函数的参数列表与依赖名称列表一一对应。在模块的所有依赖加载完毕后,该函数会被调用来定义该模块,因此该模块应该返回一个定义了本模块的object。
define(["foo1", "foo2"], function(f1, f2) {
return {
color: "blue",
size: "large",
FOO: function() {
f1.dosomething;
f2.dosomething;
}
}
}
);
加载非规范的模块
理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合。那么,怎么通过require.js来加载非规范的模块呢?
如果需要使用非规范的模块,就需要通过设置require.config()的shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名称;(2)deps数组,表明该模块的依赖性。
例如现在需要引入非规范模块backbone.js、jquery.scroll.js,可以进行如下配置:
require.config({
shim: {
'backbone': {
exports: 'Backbone'
},
'jquery.scroll': {
deps: ['jquery'],
exports: 'jQuery.fn.scroll'
}
}
});
通过上面的配置,我们就可以使用对应的非规范模块了:
require.config(["jquery", " jQuery.fn.scroll", " Backbone"], function($,jfs,Bb){
dosomething;
})