参考1、2、3
一、关于使用requireJS
js文件就几个的时候都还好,但是当程序越来越复杂,js文件也就越来得越多。
<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="4.js"></script>
<script src="5.js"></script>
<script src="6.js"></script>
这样的时候。主要问题有两个。
第一是文件越多,因为浏览器同时加载文件有限(6个),所以会造成css,图片之类的加载缓慢。浏览器就会停止响应。
第二是依赖关系,因为互相依赖,所以需要确保顺序,当之间关系复杂,就更加难以处理。
requireJS就是为了这个,异步加载,处理依赖关系。
二,下载安装
从http://requirejs.org/下载,放到工作目录内js文件夹,创建下面两个文件
index.html:
<span class="dec"><!DOCTYPE html></span>
<span class="tag"><html></span>
<span class="tag"><head></span>
<span class="tag"><script</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"js/require.js"</span><span class="tag">></script></span>
<span class="tag"><script</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span><span class="tag">></span><span class="pln">
require</span><span class="pun">([</span><span class="str">"a"</span><span class="pun">]);</span>
<span class="tag"></script></span>
<span class="tag"></head></span>
<span class="tag"><body></span>
<span class="tag"><span></span><span class="pln">body</span><span class="tag"></span></span>
<span class="tag"></body></span>
<span class="tag"></html></span>
a.js:
<span class="pln">define</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(){</span>
<span class="kwd">function</span><span class="pln"> fun1</span><span class="pun">(){</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"it works"</span><span class="pun">);</span>
<span class="pun">}</span><span class="pln">
fun1</span><span class="pun">();</span>
<span class="pun">})</span>
运行看看,弹出来”it works”,第一步完成啦~
二、进一步了解依赖
我们这里把index.html里边的
<span class="pln"> require</span><span class="pun">([</span><span class="str">"a"</span><span class="pun">]);</span>
改成
<span class="kwd">require</span><span class="pun">([</span><span class="str">"js/a"</span><span class="pun">],</span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"load finished"</span><span class="pun">);</span>
<span class="pun">})</span>
这里再试试,除了’it works’ 还有’load finished’,这样的顺序出现。
这里可以看到require 里边的中括号实际是一个数组,当你有许多个依赖时,这里就可以当作数组加载依次加载。但是就算只有一个依赖,也需要写成数组。
后边的function就是回调函数,就是当依赖加载结束,执行里边的函数。
比如我现在依赖三个模块jquery、underscore和backbone ,可以这样写:
require(['js/jquery', 'js/funnjs','js/underscore', 'js/backbone'], function ($ , funn,_, Backbone){
// some code here
});
这里边前边是依赖数组。后边那些’$’ 、’_’其实是指前边依赖加载完毕的返回对象。比如funnjs里有个return a; 那么在下边的函数内就可以用语句funn.a 来使用返回对象。
在这里有一点,就是”js/jquery’是指’js/jquery.js’.这里是把扩展名忽略了。
三、关于加载文件
其实像用’js/jquery’这样很麻烦,可以使用
<span class="kwd">require</span><span class="pun">.</span><span class="pln">config</span><span class="pun">({</span><span class="pln">
paths </span><span class="pun">:</span> <span class="pun">{</span>
<span class="str">"a"</span> <span class="pun">:</span> "js/a"
<span class="pun">}</span>
<span class="pun">})</span>
<span class="kwd">require</span><span class="pun">(</span><span class="str">"a"</span><span class="pun">],</span><span class="kwd">function</span><span class="pun">(</span><span class="pun">){</span><span class="pln">
$</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"load finished"</span><span class="pun">);</span>
<span class="pun">})</span>
<span class="pun">})</span>
也可以使用远程文件
<span class="kwd">require</span><span class="pun">.</span><span class="pln">config</span><span class="pun">({</span><span class="pln">
paths </span><span class="pun">:</span> <span class="pun">{</span>
<span class="str">"jquery"</span> <span class="pun">:</span> <span class="pun">[</span><span class="str">"http://libs.baidu.com/jquery/2.0.3/jquery"</span><span class="pun">],</span>
<span class="str">"a"</span> <span class="pun">:</span> <span class="str">"js/a"</span>
<span class="pun">}</span>
<span class="pun">})</span>
<span class="kwd">require</span><span class="pun">([</span><span class="str">"jquery"</span><span class="pun">,</span><span class="str">"a"</span><span class="pun">],</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$</span><span class="pun">){</span><span class="pln">
$</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"load finished"</span><span class="pun">);</span>
<span class="pun">})</span>
<span class="pun">})</span>
用paths还有一个功能就是配置多个地址,如果一个不能加载,就立刻换下一个。
<span class="kwd">require</span><span class="pun">.</span><span class="pln">config</span><span class="pun">({</span><span class="pln">
paths </span><span class="pun">:</span> <span class="pun">{</span>
<span class="str">"jquery"</span> <span class="pun">:</span> <span class="pun">[</span><span class="str">"http://libs.baidu.com/jquery/2.0.3/jquery"</span><span class="pun">,</span> <span class="str">"js/jquery"</span><span class="pun">],</span>
<span class="str">"a"</span> <span class="pun">:</span> <span class="str">"js/a"</span>
<span class="pun">}</span>
<span class="pun">})</span>
四、关于main.js
像这样的配置,如果每个html内都有,无疑是浪费的。所以需要把require.config做成全剧共部分。在js文件夹内创建main.js:
<span class="kwd">require</span><span class="pun">.</span><span class="pln">config</span><span class="pun">({</span><span class="pln">
paths </span><span class="pun">:</span> <span class="pun">{</span>
<span class="str">"jquery"</span> <span class="pun">:</span> <span class="pun">[</span><span class="str">"http://libs.baidu.com/jquery/2.0.3/jquery"</span><span class="pun">,</span> <span class="str">"js/jquery"</span><span class="pun">],</span>
<span class="str">"a"</span> <span class="pun">:</span> <span class="str">"js/a"</span>
<span class="pun">}</span>
<span class="pun">})</span>
将
<span class="tag"><script</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"js/require.js"</span><span class="tag">></script></span>
更换成
<span class="tag"><script</span> <span class="atn">data-main</span><span class="pun">=</span><span class="atv">"js/main"</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"js/require.js"</span><span class="tag">></script></span>
这里加入了data-main属性。这里指定的js将会在require.js加载完毕运行。每个页面就可以不用写require.config,直接使用全局设定。
五,例子1
说真的我当时看到这些,觉得,这些有啥用啊。。就有了以下的例子
index.html
<!DOCTYPE html>
<html>
<head>
<script data-main="js/main" src="js/require.js"></script>
<script type="text/javascript">
require(["js/a.js","js/b.js"],function(){
funa();
funb();
})
</script>
</head>
<body>
<span>body</span>
</body>
</html>
js/a.js
function funa(){
alert("a works");
}
js/b.js
function funb(){
alert("b works");
}
以上。
就可以在主函数内调用两个文件中的函数。
另外,RequireJS默认并没有保证一定会在页面加载完毕执行的。如果需要在加载完毕后加载。就需要一个官方模块。在官网下载domReady模块.把这个js放到js文件夹内。
<script>
require(["domReady!", "js/a.js", "js/b.js"], function() {
funa();
funb();
});
</script>
这样就能能达到目的了。
六、关于模块化设计
在传统JavaScript中,使用全局变量过于容易。但是有时候却并不需要这样,因为命名空间会过于庞大复杂。所以可以通过 AMD 规范将一个模块内的变量仅自己使用,避免声明了全局变量。使用的时候,比如b依赖a,那么c访问b中的变量,用a.b来实现。
student.js
define(function(){
return {
createStudent: function(name, gender){
return {
name: name,
gender: gender
};
}
};
});
class.js
define(function() {
var allStudents = [];
return {
classID: "001",
department: "computer",
addToClass: function(student) {
allStudents.push(student);
},
getClassSize: function() {
return allStudents.length;
}
};
}
);
主程序
require(["js/student", "js/class"], function(student, clz) {
clz.addToClass(student.createStudent("Jack", "male"));
clz.addToClass(student.createStudent("Rose", "female"));
console.log(clz.getClassSize()); // 输出 2
console.log(clz.classID) ; //输出001
});
是的,就输出一个2。还有一个班级号。
这里的clz就是指js/class return的对象组。这个看起来比较简单明了。现在复杂一点。
依赖 student 和 class 模块的 manager 模块,manager.js
define(["js/student", "js/class"], function(student, clz){
return {
addNewStudent: function(name, gender){
clz.addToClass(student.createStudent(name, gender));
},
getMyClassSize: function(){
return clz.getClassSize();
}
};
});
新的主程序
require(["js/manager"], function(manager) {
manager.addNewStudent("Jack", "male");
manager.addNewStudent("Rose", "female");
console.log(manager.getMyClassSize());// 输出 2
});
一样输出2.
这里就多了这么一句
clz.addToClass(student.createStudent(name, gender));
其实就是用前缀来区分命名空间。
然后。
暂时告一段落。。。