RequireJS 入门指南
如今最常用的 JavaScript 库之一是 RequireJS。
最近我参与的每个项目,都用到了 RequireJS,
或者是我向它们推荐了增加 RequireJS。
在这篇文章中,我将描述 RequireJS 是什么,以及它的一些基础场景。
异步模块定义(AMD)
谈起 RequireJS,你无法绕过提及 JavaScript 模块是什么,以及 AMD 是什么。
JavaScript 模块只是遵循 SRP(Single Responsibility Principle 单一职责原则)的代码段,
它暴露了一个公开的 API。
在现今 JavaScript 开发中,你可以在模块中封装许多功能,而 且在大多数项目中,
每个模块都有其自己的文件。 这使得 JavaScript 开发者日子有点难过,
因为它们需要持续不断的关注模块之间的依赖性, 按照一个特定的顺序加载这些模块,
否则 运行时将会放生错误。 当你要加载 JavaScript 模块时,就会使用 script 标签。
为了加载依赖的模块,你就要先加 载被依赖的,之后再加载依赖的。
使用 script 标签时,你需要按照此特定顺序安排它们的 加载,
而且脚本的加载是同步的。可以使用 async 和 defer 关键字使得加载异步,
但可能 因此在加载过程中丢失加载的顺序。
另一个选择是将所有的脚本捆绑打包在一起,
但在捆绑 的时候你仍然需要把它们按照正确的顺序排序。
AMD 就是这样一种对模块的定义,使模块和它的依赖可以被异步的加载,但又按照正确的 顺序。
CommonJS, 是对通用的 JavaScript 模式的标准化尝试,
它包含有 AMD 定义 ,我建议 你在继续本文之前先读一下。
在 ECMAScript 6 这个下一版本 JavaScript 规范中,有关于 输出,
输入以及模块的规范定义, 这些将成为 JavaScript 语言的一部分,
而且这不会太久。 这也是关于 RequireJS 我们想说的东西。
RequireJS?
RequireJS 是一个 Javascript 文件和模块框架,
可以从 http://requirejs.org/下载,如果 你使用 Visual Studio 也可以通过 Nuget 获取。
它支持浏览器和像 node.js 之类的服务器 环境。
使用 RequireJS,你可以顺序读取仅需要相关依赖模块。
RequireJS 所做的是,在你使用 script 标签加载你所定义的依赖时,
将这些依赖通过 head.appendChild()函数来加载他们。当依赖加载以后,RequireJS 计算出模块定义的顺 序,
并按正确的顺序进行调用。这意味着你需要做的仅仅是使用一个“根”来读取你需要的 所有功能
,然后剩下的事情只需要交给 RequireJS 就行了。为了正确的使用这些功能,
你 定义的所有模块都需要使用 RequireJS 的 API,否者它不会像期望的那样工作。
RequireJS API 存在于 RequireJS 载入时创建的命名空间 requirejs 下。
其主要 API 主要是 下面三个函数:
?
define– 该函数用户创建模块。
每个模块拥有一个唯一的模块 ID,
它被用于 RequireJS 的运行时函数,
define 函数是一个全局函数,
不需要使用 requirejs 命名空间.
?
require– 该函数用于读取依赖。
同样它是一个全局函数,
不需要使用 requirejs 命名空 间.
?
config– 该函数用于配置 RequireJS.
在后面,我们将教你如果使用这些函数,
但首先让我们先了解下 RequireJS 的加载流程。
data-main 属性
当你下载 RequireJS 之后,
你要做的第一件事情就是理解 RequireJS 是怎么开始工作的。
当 RequireJS 被加载的时候,
它会使用 data-main 属性去搜寻一个脚本文件(它应该是与 使用 src 加载 RequireJS 是相同的脚本)。
data-main 需要给所有的脚本文件设置一个根 路径。
根据这个根路径,RequireJS 将会去加载所有相关的模块。下面的脚本是一个使用 data-main 例子:
1
<script src="scripts/require.js" data-main="scripts/app.js"></script>
另外一种方式定义根路劲是使用配置函数,后面我们将会看到。
requireJs 假设所有的依赖 都是脚本,那么当你声明一个脚本依赖的时候你不需要使用.js 后缀。
配置函数
如果你想改变 RequireJS 的默认配置来使用自己的配置,
你可以使用 require.configh 函数。
config 函数需要传入一个可选参数对象,这个可选参数对象包括了许多的配置参数选项。
下面是一些你可以使用的配置:
baseUrl——用于加载模块的根路径。
paths——用于映射不存在根路径下面的模块路径。
shims——配置在脚本/模块外面并没有使用 RequireJS 的函数依赖并且初始化函数
假设 underscore 并没有使用 RequireJS 定义,
但是你还是想通过 RequireJS 来使用 它,那么你就需要在配置中把它定义为一个 shim。
?
deps——加载依赖关系数组
下面是使用配置的一个例子:
01 require.config({ 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 });
在这个例子中把根路径设置为了 scripts/app, 由 lib 开始的每个模块都被配置在 scripts/lib
//By default load any module IDs from scripts/app
baseUrl: 'scripts/app',
//except, if the module ID starts with
"lib" paths: { lib: '../lib' },
// load backbone as a shim shim:
{ 'backbone': { //The underscore script dependency should be loaded before loading backbone.js deps:
['underscore'], // use the global 'Backbone' as the module name. exports: 'Backbone' } }
文件夹下面,backbone 加载的是一个 shim 依赖。
用 RequireJS 定义模块
模块是进行了内部实现封装、暴露接口和合理限制范围的对象。
ReuqireJS 提供了 define 函数用于定义模块。
按章惯例每个 Javascript 文件只应该定义一个模块。
define 函数接受 一个依赖数组和一个包含模块定义的函数。
通常模块定义函数会把前面的数组中的依赖模块 按顺序做为参数接收。
例如,下面是一个简单的模块定义:
01 define(["logger"], function(logger) { 02 03 04 05 06 07 08 09 10 );
我们看,一个包含了 logger 的模块依赖数组被传给了 define 函数,该模块后面会被调用。
同样我们看所定义的模块中有一个名为 logger 的参数,
它会被设置为 logger 模块。
每一 个模块都应该返回它的 API.这个示例中我们有两个属性(firstName 和 lastName)和一个函 数(sayHello)。
然后,只要你后面定义的模块通过 ID 来引用这个模块,你就可以使用其暴 露的 API。
return { firstName: “John", lastName: “Black“, sayHello: function () { logger.log(‘hello’); } } }
使用 require 函数
在 RequireJS 中另外一个非常有用的函数是 require 函数。
require 函数用于加载模块依赖 但并不会创建一个模块。
例如: 下面就是使用 require 定义了能够使用 jQuery 的一个函数。
view source print?
1 require(['jquery'], function ($) { 2 3 });
//jQuery was loaded and can be used now
小结
在这篇文章中我介绍了 RequireJS 库,它是我创建每个 Javascript 项目都会用到的库函数之 一。
它不仅仅用于加载模块依赖和相关的命令,RequireJS 帮助我们写出模块化的 JavaScript 代码,这非常有利于代码的可扩展性和重用性。