下面我们先来看一个简单的例子,这个例子通过定义一个 student 模块和一个 class 模块,在主程序中实现创建 student 对象并将 student 对象放到 class 中去。
案例四: student 模块,student.js
define(function(){ return { createStudent: function(name, gender){ return { name: name, gender: gender }; } }; });
案例五:class 模块,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 });
student 模块和 class 模块都是独立的模块,下面我们再定义一个新的模块,这个模块依赖 student 和 class 模块,这样主程序部分的逻辑也可以包装进去了。
案例七: 依赖 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 });
通过上面的代码示例,我们已经清楚的了解了如何写一个模块,这个模块如何被使用,模块间的依赖关系如何定义。还是有一些使用技巧需要提示一下:
尽量不要提供模块的 ID,如 AMD 规范所述,这个 ID 是可选项,如果提供了,在 RequireJS 的实现中会影响模块的可迁移性,文件位置变化会导致需要手动修改该 ID。
每个 JavaScript 文件只定义一个模块,模块名称和文件路径的查找算法决定了这种方式是最优的,多个的模块和文件会被优化器进行优化。 避免模块的循环依赖,如果实在避免不了,可以模块中加上对”require”模块的依赖,在代码中直接用
require(”dependencyModuleName”)
配置 RequireJS:
前面的介绍中,我们似乎忽略了一个基本问题,模块名字是怎么来的?当我在 require 一个模块时,这个模块是如何映射到具体的 JavaScript 文件上去?这就涉及到如何配置 RequireJS。
最简化的加载 RequireJS 的方式如案例2 所示,在这种情况下,我们没有指定一个 baseUrl 和 paths 给 RequireJS,如果通过如案例10 所示方式,则 data-main 指定了一个在当前 index.html 目录并行的文件夹下的 /js/main.js 作为程序入口,而 /js 目录也将作为 baseUrl 在其他模块定义时候使用。
案例九:载入 require.js
<script data-main="js/main" src="https://www.jb51.net/scripts/require.js"></script>
因此,我们前面示例中的所有模块依赖,都可以去掉”js/”,直接写 ”student”, ”class”,”manager” 等。 一种更为直接的方式显示指定 baseUrl 和 paths 就是利用 require.config 来设置这些参数。如案例十 所示。
案例十. 配置 RequireJS
<script type="text/javascript" src="https://www.jb51.net/article/js/require.js"></script> <script type="text/javascript"> require.config({ baseUrl: "./js", paths: { "some": "some/v1" }, waitSeconds: 10 }); require( ["some/module", "my/module", "./js/a.js"], function(someModule, myModule) {} ); </script>
baseUrl指明的是所有模块的 base URL,比如”my/module”所加载的 script实际上就是 /js/my/module.js。注意,以 .js 结尾的文件加载时不会使用该 baseUrl,它们仍然会使用当前 index.html所在的相对路径来加载,所以仍然要加上”./js/”。如果 baseUrl没有指定,那么就会使用 data-main中指定的路径。
paths 中定义的路径是用于替换模块中的路径,如上例中的 some/module 具体的 JavaScript 文件路径是 /js/some/v1/module.js 。 waitSeconds 是指定最多花多长等待时间来加载一个 JavaScript 文件,用户不指定的情况下默认为 7 秒。
另外一个重要的配置是 packages,它可以指定其他符合 CommonJS AMD 规范的目录结构,由此带来了丰富的扩展性。如 Dojo、jQuery 等的模块也可以通过该配置来让 RequireJS 加载。