在介绍requireJS之前,要先说一下模块规范。目前,通行的Javascript模块规范共有两种:CommonJS和AMD。
var math = require('math'); //加载指定模块 math.add(2,3);
由于一个重大的局限,使得CommonJS规范不适用于浏览器环境。
var math = require('math'); //加载指定模块 math.add(2,3);第二行math.add(2, 3),在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。
这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。
因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
require(['math'], function (math) { math.add(2, 3); });目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js。
<script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></script>缺点:
<script src="jsFile.js" async="true"></script> <script src="jsFile.js" defer></script>(2)另一个选择是将所有的脚本捆绑打包在一起,但在捆绑的时候你仍然需要把它们按照正确的顺序排序。
RequireJS使用head.appendChild()将每一个依赖加载为一个script标签。
RequireJS等待所有的依赖加载完毕,计算出模块定义函数正确调用顺序,然后依次调用它们。
在同步加载的服务端JavaScript环境中,可简单地重定义require.load()来使用RequireJS。
<pre name="code" class="html"><script src="js/require.js"></script>载这个文件,也可能造成网页失去响应,解决方法:一放到网页底部加载;二异步加载
<script src="js/require.js" defer async="true"></script>
<script src="js/require.js" data-main="js/main"></script> /* main.js */ require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){ // some code here });require.js会先加载jQuery、underscore和backbone,然后再运行回调函数。主模块的代码就写在回调函数中。
<script data-main="./js/main.js" src="./js/libs/require.js" ></script> <script src="./js/require.config.js"></script>
require.config({ // 所有模块的查找根路径 baseUrl: "js/lib", // paths指定各个模块的加载路径 paths: { "jquery": "jquery.min", "underscore": "underscore.min", "backbone": "backbone.min" } });
/* math.js */ define(function (){ var add = function (x,y){ return x+y; }; return { add: add }; }); /* main.js 加载方法 */ require(['math'], function (math){ console.log(math.add(1,2)); });
require.config({ shim: { 'underscore':{ // exports值(输出的变量名),表明这个模块外部调用时的名称 exports: '_' }, 'backbone': { // deps数组,表明该模块的依赖 deps: ['underscore', 'jquery'], exports: 'Backbone' } } });
requirejs.config({ map: { 'some/newmodule': { 'foo': 'foo1.2' }, 'some/oldmodule': { 'foo': 'foo1.1' }, '*': { 'foo': 'foo1.0' } } });foo1.0.js
当“some/newmodule”调用了“require('foo')”,它将获取到foo1.2.js文件;
当“some/oldmodule”调用了“require('foo')”,它将获取到foo1.1.js;
当其他调用了“require('foo')”,它将获取到foo1.0.js
require(['domready!'], function (doc){ // called once the DOM is ready });(2)text和image插件,则是允许require.js加载文本和图片文件。
define([ 'text!review.txt', 'image!cat.jpg' ], function(review,cat){ console.log(review); document.body.appendChild(cat); } );(3)json和mdown插件,用于加载json文件和markdown文件。