原文地址:http://udn.yyuap.com/forum.php?mod=viewthread&tid=50379javascript
这是 RequireJS 2.0 的API,对应的官方文档版本号是2.1.9
目录
用法 ———————————————— §§ 1-1.2
简单的值对 ———————————– § 1.2.1
函数式定义 ———————————– § 1.2.2
存在依赖的函数式定义 ————————– § 1.2.3
将模块定义为一个函数 ————————– § 1.2.4
简单包装CommonJS来定义模块 ——————– § 1.2.5
定义一个命名模块 —————————— § 1.2.6
其余注意事项 ——————————— § 1.2.7
循环依赖 ————————————- § 1.2.8
JSONP服务依赖 ——————————– § 1.2.9
undefine一个模块 —————————– § 1.2.10
加载JavaScript文件 ——————————- § 1.1
定义模块 —————————————– § 1.2
机理 ———————————————— §§ 2
配置项 ———————————————- § 3
进阶应用 ——————————————— §§ 4-4.6
在IE中捕获加载错 —————————– § 4.6.1
require([]) errbacks ———————– § 4.6.2
paths备错配置 ——————————- § 4.6.3
全局的 requirejs.onError ——————– § 4.6.4
从包中加载模块 ———————————— § 4.1
多版本支持 ————————————— § 4.2
在页面加载以后加载代码 —————————- § 4.3
对Web Worker的支持 —————————— § 4.4
对Rhino的支持 ———————————– § 4.5
处理错误 —————————————- § 4.6
加载器插件 ——————————————- §§ 5-5.3
指定文本文件依赖 ———————————- § 5.1
页面加载事件及DOM Ready ————————— § 5.2
define I18N bundle —————————— § 5.3
php
§ 1.1加载JavaScript文件
RequireJS的目标是鼓励代码的模块化,它使用了不一样于传统<script>标签的脚本加载步骤。能够用它来加速、优化代码,但其主要目的仍是为了代码的模块化。它鼓励在使用脚本时以module ID替代URL地址。
RequireJS以一个相对于baseUrl的地址来加载全部的代码。 页面顶层<script>标签含有一个特殊的属性data-main,require.js使用它来启动脚本加载过程,而baseUrl通常设置到与该属性相一致的目录。下列示例中展现了baseUrl的设置:
css
baseUrl亦可经过RequireJS config手动设置。若是没有显式指定config及data-main,则默认的baseUrl为包含RequireJS的那个HTML页面的所属目录。
RequireJS默认假定全部的依赖资源都是js脚本,所以无需在module ID上再加”.js”后缀,RequireJS在进行module ID到path的解析时会自动补上后缀。你能够经过paths config设置一组脚本,这些有助于咱们在使用脚本时码更少的字。
有时候你想避开”baseUrl + paths”的解析过程,而是直接指定加载某一个目录下的脚本。此时能够这样作:若是一个module ID符合下述规则之一,其ID解析会避开常规的”baseUrl + paths”配置,而是直接将其加载为一个相对于当前HTML文档的脚本:
以”.js”结尾;
以”/”开头;
包含URL协议,如”http:”、”https:”
通常来讲,最好仍是使用baseUrl及”paths” config去设置module ID。它会给你带来额外的灵活性,如便于脚本的重命名、重定位等。 同时,为了不凌乱的配置,最好不要使用多级嵌套的目录层次来组织代码,而是要么将全部的脚本都放置到baseUrl中,要么分置为项目库/第三方库的一个扁平结构,以下:www/
app/
lib/
app.js
sub.js
jquery.js
canvas.js
index.html
js/
在index.html中:html
在app.js中:java
注意在示例中,三方库如jQuery没有将版本号包含在他们的文件名中。咱们建议将版本信息放置在单独的文件中来进行跟踪。使用诸如volo这类的工具,能够将package.json打上版本信息,并在磁盘上保持文件名为”jquery.js”。这有助于你保持配置的最小化,避免为每一个库版本设置一条path。例如,将”jquery”配置为”jquery-1.7.2″。
理想情况下,每一个加载的脚本都是经过define()来定义的一个模块;但有些”浏览器全局变量注入”型的传统/遗留库并无使用define()来定义它们的依赖关系,你必须为此使用shim config来指明它们的依赖关系。 若是你没有指明依赖关系,加载可能报错。这是由于基于速度的缘由,RequireJS会异步地以无序的形式加载这些库。
§ 1.2定义模块
模块不一样于传统的脚本文件,它良好地定义了一个做用域来避免全局名称空间污染。它能够显式地列出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入,而无需引用全局变量。RequireJS的模块是模块模式的一个扩展,其好处是无需全局地引用其余模块。
RequireJS的模块语法容许它尽快地加载多个模块,虽然加载的顺序不定,但依赖的顺序最终是正确的。同时由于无需建立全局变量,甚至能够作到在同一个页面上同时加载同一模块的不一样版本。
(若是你熟悉ConmmonJS,可参看CommonJS的注释信息以了解RequireJS模块到CommonJS模块的映射关系)。
一个磁盘文件应该只定义 1 个模块。多个模块可使用内置优化工具将其组织打包。
§ 1.2.1 简单的值对
若是一个模块仅含值对,没有任何依赖,则在define()中定义这些值对就行了:node
§ 1.2.2 函数式定义
若是一个模块没有任何依赖,但须要一个作setup工做的函数,则在define()中定义该函数,并将其传给define():jquery
§ 1.2.3 存在依赖的函数式定义
若是模块存在依赖:则第一个参数是依赖的名称数组;第二个参数是函数,在模块的全部依赖加载完毕后,该函数会被调用来定义该模块,所以该模块应该返回一个定义了本模块的object。依赖关系会以参数的形式注入到该函数上,参数列表与依赖名称列表一一对应。
git
本示例建立了一个my/shirt模块,它依赖于my/cart及my/inventory。磁盘上各文件分布以下:
my/cart.js
my/inventory.js
my/shirt.js
模块函数以参数”cart”及”inventory”使用这两个以”./cart”及”./inventory”名称指定的模块。在这两个模块加载完毕以前,模块函数不会被调用。
严重不鼓励模块定义全局变量。遵循此处的定义模式,可使得同一模块的不一样版本并存于同一个页面上(参见 高级用法 )。另外,函参的顺序应与依赖顺序保存一致。
返回的object定义了”my/shirt”模块。这种定义模式下,”my/shirt”不做为一个全局变量而存在。
§ 1.2.4 将模块定义为一个函数
对模块的返回值类型并无强制为必定是个object,任何函数的返回值都是容许的。此处是一个返回了函数的模块定义:
github
§ 1.2.5 简单包装CommonJS来定义模块
若是你现有一些以CommonJS模块格式编写的代码,而这些代码难于使用上述依赖名称数组参数的形式来重构,你能够考虑直接将这些依赖对应到一些本地变量中进行使用。你可使用一个CommonJS的简单包装来实现:
web
该包装方法依靠Function.prototype.toString()将函数内容赋予一个有意义的字串值,但在一些设备如PS3及一些老的Opera手机浏览器中不起做用。考虑在这些设备上使用优化器将依赖导出为数组形式。
更多的信息可参看CommonJS Notes页面,以及”Why AMD”页面的”Sugar”段落。
§ 1.2.6 定义一个命名模块
你可能会看到一些define()中包含了一个模块名称做为首个参数:
这些常由优化工具生成。你也能够本身显式指定模块名称,但这使模块更不具有移植性——就是说若你将文件移动到其余目录下,你就得重命名。通常最好避免对模块硬编码,而是交给优化工具去生成。优化工具须要生成模块名以将多个模块打成一个包,加快到浏览器的载人速度。
§ 1.2.7 其余注意事项
一个文件一个模块: 每一个Javascript文件应该只定义一个模块,这是模块名-至-文件名查找机制的天然要求。多个模块会被优化工具组织优化,但你在使用优化工具时应将多个模块放置到一个文件中。
define()中的相对模块名: 为了能够在define()内部使用诸如require(“./relative/name”)的调用以正确解析相对名称,记得将”require”自己做为一个依赖注入到模块中:
或者更好地,使用下述为转换CommonJS模块所设的更短的语法:
该形式利用了Function.prototype.toString()去查找require()调用,而后将其与”require”一块儿加入到依赖数组中,这样代码能够正确地解析相对路径了。
相对路径在一些场景下格外有用,例如:为了以便于将代码共享给其余人或项目,你在某个目录下建立了一些模块。你能够访问模块的相邻模块,无需知道该目录的名称。
生成相对于模块的URL地址: 你可能须要生成一个相对于模块的URL地址。你能够将”require”做为一个依赖注入进来,而后调用require.toUrl()以生成该URL:
控制台调试: 若是你须要处理一个已经过require(["module/name"], function(){})调用加载了的模块,可使用模块名做为字符串参数的require()调用来获取它:
注意这种形式仅在”module/name”已经由其异步形式的require(["module/name"])加载了后才有效。只能在define内部使用形如”./module/name”的相对路径。
§ 1.2.8 循环依赖
若是你定义了一个循环依赖(a依赖b,b同时依赖a),则在这种情形下当b的模块函数被调用的时候,它会获得一个undefined的a。b能够在模块已经定义好后用require()方法再获取(记得将require做为依赖注入进来):
通常说来你无需使用require()去获取一个模块,而是应当使用注入到模块函数参数中的依赖。循环依赖比较罕见,它也是一个重构代码从新设计的警示灯。但无论怎样,有时候仍是要用到循环依赖,这种情形下就使用上述的require()方式来解决。
若是你熟悉CommonJS,你能够考虑使用exports为模块创建一个空object,该object能够当即被其余模块引用。在循环依赖的两头都如此操做以后,你就能够安全地持有其余模块了。这种方法仅在每一个模块都是输出object做为模块值的时候有效,换成函数无效。
或者,若是你使用依赖注入数组的步骤,则可用注入特殊的”exports”来解决:
§ 1.2.9 JSONP服务依赖
JSONP是在javascript中服务调用的一种方式。它仅需简单地经过一个script标签发起HTTP GET请求,是实现跨域服务调用一种公认手段。
为了在RequireJS中使用JSON服务,需要将callback参数的值指定为”define”。这意味着你可将获取到的JSONP URL的值当作是一个模块定义。
下面是一个调用JSONP API端点的示例。该示例中,JSONP的callback参数为”callback”,所以”callback=define”告诉API将JSON响应包裹到一个”define()”中:
JSONP的这种用法应仅限于应用的初始化中。一旦JSONP服务超时,其余经过define()定义了的模块也可能得不得执行,错误处理不是十分健壮。
仅支持返回值类型为JSON object的JSONP服务,其余返回类型如数组、字串、数字等都不能支持。
这种功能不应用于long-polling类的JSONP链接——那些用来处理实时流的API。这些API在接收响应后通常会作script的清理,而RequireJS则只能获取该JSONP URL一次——后继使用require()或define()发起的的对同一URL的依赖(请求)只会获得一个缓存过的值。
JSONP调用错误通常以服务超时的形式出现,由于简单加载一个script标签通常不会获得很 详细的网络错误信息。你能够override requirejs.onError()来过去错误。更多的信息请参看错误处理部分。
§ 1.2.10 undefine一个模块
有一个全局函数requirejs.undef()用来undefine一个模块。它会重置loader的内部状态以使其忘记以前定义的一个模块。
可是如有其余模块已将此模块做为依赖使用了,该模块就不会被清除,因此该功能仅在无其余模块持有该模块时的错误处理中,或者当将来须要加载该模块时有点用。参见备错(errbacks)段的示例。
若是你打算在undefine时作一些复杂的依赖图分析,则半私有的onResourceLoad API可能对你有用。
§ 2 机理
RequireJS使用head.appendChild()将每个依赖加载为一个script标签。
RequireJS等待全部的依赖加载完毕,计算出模块定义函数正确调用顺序,而后依次调用它们。
在同步加载的服务端JavaScript环境中,可简单地重定义require.load()来使用RequireJS。build系统就是这么作的。该环境中的require.load实现可在build/jslib/requirePatch.js中找到。
将来可能将该部分代码置入require/目录下做为一个可选模块,这样你能够在你的宿主环境中使用它来得到正确的加载顺序。
§ 3 配置项
当在顶层HTML页面(或不做为一个模块定义的顶层脚本文件)中,可将配置做为首项放入:
或者,你将配置做为全局变量”require”在require.js加载以前进行定义,它会被自动应用。下面的示例定义的依赖会在require.js一旦定义了require()以后即被加载:
注意:最好使用 var require = {} 的形式而不是 window.require = {}的形式。后者在IE中运行不正常。
支持的配置项:
baseUrl :全部模块的查找根路径。因此上面的示例中,”my/module”的标签src值是”/another/path/my/module.js”。当加载纯.js文件(依赖字串以/开头,或者以.js结尾,或者含有协议),不会使用baseUrl。所以a.js及b.js都在包含上述代码段的HTML页面的同目录下加载。
如未显式设置baseUrl,则默认值是加载require.js的HTML所处的位置。若是用了data-main属性,则该路径就变成baseUrl。
baseUrl可跟require.js页面处于不一样的域下,RequireJS脚本的加载是跨域的。惟一的限制是使用text! plugins加载文本内容时,这些路径应跟页面同域,至少在开发时应这样。优化工具会将text! plugin资源内联,所以在使用优化工具以后你可使用跨域引用text! plugin资源的那些资源。
paths :path映射那些不直接放置于baseUrl下的模块名。设置path时起始位置是相对于baseUrl的,除非该path设置以”/”开头或含有URL协议(如http:)。在上述的配置下,”some/module”的script标签src值是”/another/path/some/v1.0/module.js”。
用于模块名的path不该含有.js后缀,由于一个path有可能映射到一个目录。路径解析机制会自动在映射模块名到path时添加上.js后缀。在文本模版之类的场景中使用require.toUrl()时它也会添加合适的后缀。
在浏览器中运行时,可指定路径的备选(fallbacks),以实现诸如首先指定了从CDN中加载,一旦CDN加载失败则从本地位置中加载这类的机制。
shim: 为那些没有使用define()来声明依赖关系、设置模块的”浏览器全局变量注入”型脚本作依赖和导出配置。
下面有个示例,它须要 RequireJS 2.1.0+,而且假定backbone.js、underscore.js 、jquery.js都装于baseUrl目录下。若是没有,则你可能须要为它们设置paths config:
RequireJS 2.0.*中,shim配置中的”exports”属性能够是一个函数而不是字串。这种状况下它就起到上述示例中的”init”属性的功能。 RequireJS 2.1.0+中加入了”init”承接库加载后的初始工做,以使exports做为字串值被enforceDefine所使用。
那些仅做为jQuery或Backbone的插件存在而不导出任何模块变量的”模块”们,shim配置可简单设置为依赖数组:
但请注意,若你想在IE中使用404加载检测以启用path备选(fallbacks)或备错(errbacks),则须要给定一个字串值的exports以使loader可以检查出脚本是否实际加载了(init中的返回值不会用于enforceDefine检查中):
“shim”配置的重要注意事项:
shim配置仅设置了代码的依赖关系,想要实际加载shim指定的或涉及的模块,仍然须要一个常规的require/define调用。设置shim自己不会触发代码的加载。
请仅使用其余”shim”模块做为shim脚本的依赖,或那些没有依赖关系,而且在调用define()以前定义了全局变量(如jQuery或lodash)的AMD库。不然,若是你使用了一个AMD模块做为一个shim配置模块的依赖,在build以后,AMD模块可能在shim托管代码执行以前都不会被执行,这会致使错误。终极的解决方案是将全部shim托管代码都升级为含有可选的AMD define()调用。
“shim”配置的优化器重要注意事项:
您应当使用 mainConfigFile build配置项来指定含有shim配置的文件位置,不然优化器不会知晓shim配置。另外一个手段是将shim配置复制到build profile中。
不要在一个build中混用CDN加载和shim配置。示例场景,如:你从CDN加载jQuery的同时使用shim配置加载依赖于jQuery的原版Backbone。不要这么作。您应该在build中将jQuery内联而不是从CDN加载,不然build中内联的Backbone会在CDN加载jQuery以前运行。这是由于shim配置仅延时加载到全部的依赖已加载,而不会作任何define的自动装裹(auto-wrapping)。在build以后,全部依赖都已内联,shim配置不能延时执行非define()的代码。define()的模块能够在build以后与CDN加载代码一并工做,由于它们已将本身的代码合理地用define装裹了,在全部的依赖都已加载以前不会执行。所以记住:shim配置仅是个处理非模块(non-modular)代码、遗留代码的将就手段,如能够应尽可能使用define()的模块。
对于本地的多文件build,上述的CDN加载建议仍然适用。任何shim过的脚本,它们的依赖必须加载于该脚本执行以前。这意味着要么直接在含有shim脚本的build层build它的依赖,要么先使用require([], function (){})调用来加载它的依赖,而后对含有shim脚本的build层发出一个嵌套的require([])调用。
若是您使用了uglifyjs来压缩代码,不要将uglify的toplevel选项置为true,或在命令行中不要使用 -mt。 该选项会破坏shim用于找到exports的全局名称。
map: 对于给定的模块前缀,使用一个不一样的模块ID来加载该模块。
该手段对于某些大型项目很重要:若有两类模块须要使用不一样版本的”foo”,但它们之间仍须要必定的协同。
在那些基于上下文的多版本实现中很难作到这一点。并且,paths配置仅用于为模块ID设置root paths,而不是为了将一个模块ID映射到另外一个。
map示例:
若是各模块在磁盘上分布以下:
foo1.0.js
foo1.2.js
some/
newmodule.js
oldmodule.js
当“some/newmodule”调用了“require(‘foo’)”,它将获取到foo1.2.js文件;而当“some/oldmodule”调用“`require(‘foo’)”时它将获取到foo1.0.js。
该特性仅适用于那些调用了define()并将其注册为匿名模块的真正AMD模块脚本。而且,请在map配置中仅使用绝对模块ID,“../some/thing”之类的相对ID不能工做。
另外在map中支持“*”,意思是“对于全部的模块加载,使用本map配置”。若是还有更细化的map配置,会优先于“*”配置。示例:
意思是除了“some/oldmodule”外的全部模块,当要用“foo”时,使用“foo1.2”来替代。对于“some/oldmodule”本身,则使用“foo1.0”。
config:经常须要将配置信息传给一个模块。这些配置每每是application级别的信息,须要一个手段将它们向下传递给模块。在RequireJS中,基于requirejs.config()的config配置项来实现。要获取这些信息的模块能够加载特殊的依赖“module”,并调用module.config()。示例:
r
若要将config传给包,将目标设置为包的主模块而不是包ID:
packages:从CommonJS包(package)中加载模块。参见从包中加载模块。
waitSeconds:在放弃加载一个脚本以前等待的秒数。设为0禁用等待超时。默认为7秒。
context:命名一个加载上下文。这容许require.js在同一页面上加载模块的多个版本,若是每一个顶层require调用都指定了一个惟一的上下文字符串。想要正确地使用,请参考多版本支持一节。
deps:指定要加载的一个依赖数组。当将require设置为一个config object在加载require.js以前使用时颇有用。一旦require.js被定义,这些依赖就已加载。使用deps就像调用require([]),但它在loader处理配置完毕以后就当即生效。它并不阻塞其余的require()调用,它仅是指定某些模块做为config块的一部分而异步加载的手段而已。
callback:在deps加载完毕后执行的函数。当将require设置为一个config object在加载require.js以前使用时颇有用,其做为配置的deps数组加载完毕后为require指定的函数。
enforceDefine:若是设置为true,则当一个脚本不是经过define()定义且不具有可供检查的shim导出字串值时,就会抛出错误。参考在IE中捕获加载错误一节。
xhtml:若是设置为true,则使用document.createElementNS()去建立script元素。
urlArgs:RequireJS获取资源时附加在URL后面的额外的query参数。做为浏览器或服务器未正确配置时的“cache bust”手段颇有用。使用cache bust配置的一个示例:
在开发中这颇有用,但请记得在部署到生成环境以前移除它。
scriptType:指定RequireJS将script标签插入document时所用的type=”"值。默认为“text/javascript”。想要启用Firefox的JavaScript 1.8特性,可以使用值“text/javascript;version=1.8”。
§ 4 进阶应用
§ 4.1从包中加载模块
RequireJS支持从CommonJS包结构中加载模块,但须要一些额外的配置。具体地,支持以下的CommonJS包特性:
一个包能够关联一个模块名/前缀。
package config可为特定的包指定下述属性:
重要事项:
虽然包能够有CommonJS的目录结构,但模块自己应为RequireJS可理解的模块格式。例外是:若是你在用r.js Node适配器,模块能够是传统的CommonJS模块格式。你可使用CommonJS转换工具来将传统的CommonJS模块转换为RequireJS所用的异步模块格式。
一个项目上下文中仅能使用包的一个版本。你可使用RequireJS的多版本支持来加载两个不一样的模块上下文;但若你想在同一个上下文中使用依赖了不一样版本的包C的包A和B,就会有问题。将来可能会解决此问题。
若是你使用了相似于入门指导中的项目布局,你的web项目应大体以以下的布局开始(基于Node/Rhino的项目也是相似的,只不过使用scripts目录中的内容做为项目的顶层目录):
project-directory/
require.js
project.html
scripts/
而下面的示例中使用了两个包,cart及store:
project-directory/
main.js
util.js
main.js
project.html
cart/
store/
main.js
require.js
project.html会有以下的一个script标签:
这会指示require.js去加载scripts/main.js。main.js使用“packages”配置项来设置相对于require.js的各个包,此例中是源码包“cart”及“store”:
对“cart”的依赖请求会从scripts/cart/main.js中加载,由于“main”是RequireJS默认的包主模块。对“store/util”的依赖请求会从scripts/store/util.js加载。
若是“store”包不采用“main.js”约定,以下面的结构:
project-directory/
cart/
store/
main.js
package.json
require.js
main.js
store.js
util.js
project.html
scripts/
则RequireJS的配置应以下:
减小麻烦期间,强烈建议包结构听从“main.js”约定。
§ 4.2多版本支持
如配置项一节中所述,能够在同一页面上以不一样的“上下文”配置项加载同一模块的不一样版本。require.config()返回了一个使用该上下文配置的require函数。下面是一个加载不一样版本(alpha及beta)模块的示例(取自test文件中):
注意“require”被指定为模块的一个依赖,这就容许传递给函数回调的require()使用正确的上下文来加载多版本的模块。若是“require”没有指定为一个依赖,则极可能会出现错误。
§ 4.3在页面加载以后加载代码
上述多版本示例中也展现了如何在嵌套的require()中迟后加载代码。
§ 4.4对Web Worker的支持
从版本0.12开始,RequireJS可在Web Worker中运行。能够经过在web worker中调用importScripts()来加载require.js(或包含require()定义的JS文件),而后调用require就行了。
你可能须要设置baseUrl配置项来确保require()可找到待加载脚本。
你能够在unit test使用的一个文件中找到一个例子。
§ 4.5对Rhino的支持
RequireJS可经过r.js适配器用在Rhino中。参见r.js的README。
§ 4.6处理错误
一般的错误都是404(未找到)错误,网络超时或加载的脚本含有错误。RequireJS有些工具来处理它们:require特定的错误回调(errback),一个“paths”数组配置,以及一个全局的requirejs.onError事件。
传入errback及requirejs.onError中的error object一般包含两个定制的属性:
requireType:含有类别信息的字串值,如“timeout”,“nodefine”, “scripterror”
requireModules: 超时的模块名/URL数组。
若是你获得了requireModules错,可能意味着依赖于requireModules数组中的模块的其余模块未定义。
§ 4.6.1 在IE中捕获加载错
Internet Explorer有一系列问题致使检测errbacks/paths fallbacks中的加载错 比较困难:
IE 6-8中的script.onerror无效。没有办法判断是否加载一个脚本会致使404错;更甚地,在404中依然会触发state为complete的onreadystatechange事件。
IE 9+中script.onerror有效,但有一个bug:在执行脚本以后它并不触发script.onload事件句柄。所以它没法支持匿名AMD模块的标准方法。因此script.onreadystatechange事件仍被使用。可是,state为complete的onreadystatechange事件会在script.onerror函数触发以前触发。
所以IE环境下很难一箭双鵰:匿名AMD(AMD模块机制的核心优点)和可靠的错误检测。
但若是你的项目里使用了define()来定义全部模块,或者为其余非define()的脚本使用shim配置指定了导出字串,则若是你将enforceDefine配置项设为true,loader就能够经过检查define()调用或shim全局导出值来确认脚本的加载无误。
所以若是你打算支持Internet Explorer,捕获加载错,并使用了define()或shim,则记得将enforceDefine设置为true。参见下节的示例。
注意:若是你设置了enforceDefine: true,并且你使用data-main=”"来加载你的主JS模块,则该主JS模块必须调用define()而不是require()来加载其所需的代码。主JS模块仍然可调用require/requirejs来设置config值,但对于模块加载必须使用define()。
若是你使用了almond而不是require.js来build你的代码,记得在build配置项中使用insertRequire来在主模块中插入一个require调用 —— 这跟data-main的初始化require()调用起到相同的目的。
§ 4.6.2 require([]) errbacks
当与requirejs.undef()一同使用errback时,容许你检测模块的一个加载错,而后undefine该模块,并重置配置到另外一个地址来进行重试。
一个常见的应用场景是先用库的一个CDN版本,若是其加载出错,则切换到本地版本:
使用“requirejs.undef()”,若是你配置到不一样的位置并从新尝试加载同一模块,则loader会将依赖于该模块的那些模块记录下来并在该模块从新加载成功后去加载它们。
注意:errback仅适用于回调风格的require调用,而不是define()调用。define()仅用于声明模块。
§ 4.6.3 paths备错配置
上述模式(检错,undef()模块,修改paths,重加载)是一个常见的需求,所以有一个快捷设置方式。paths配置项容许数组值:
上述代码先尝试加载CDN版本,若是出错,则退回到本地的lib/jquery.js。
注意:paths备错仅在模块ID精确匹配时工做。这不一样于常规的paths配置,常规配置可匹配模块ID的任意前缀部分。备错主要用于很是的错误恢复,而不是常规的path查找解析,由于那在浏览器中是低效的。
§ 4.6.4 全局的 requirejs.onError
为了捕获在局域的errback中未捕获的异常,你能够重载requirejs.onError():
§ 5加载器插件
RequireJS支持加载器插件。使用它们可以加载一些对于脚本正常工做很重要的非JS文件。RequireJS的wiki有一个插件的列表。本节讨论一些由RequireJS一并维护的特定插件:
§ 5.1指定文本文件依赖
若是都能用HTML标签而不是基于脚本操做DOM来构建HTML,是很不错的。但没有好的办法在JavaScript文件中嵌入HTML。所能作的仅是在js中使用HTML字串,但这通常很难维护,特别是多行HTML的状况下。
RequireJS有个text.js插件能够帮助解决这个问题。若是一个依赖使用了text!前缀,它就会被自动加载。参见text.js的README文件。
§ 5.2页面加载事件及DOM Ready
RequireJS加载模块速度很快,颇有可能在页面DOM Ready以前脚本已经加载完毕。须要与DOM交互的工做应等待DOM Ready。现代的浏览器经过DOMContentLoaded事件来知会。
可是,不是全部的浏览器都支持DOMContentLoaded。domReady模块实现了一个跨浏览器的方法来断定什么时候DOM已经ready。下载并在你的项目中如此用它:
基于DOM Ready是个常规需求,像上述API中的嵌套调用方式,理想状况下应避免。domReady模块也实现了Loader Plugin API,所以你可使用loader plugin语法(注意domReady依赖的!前缀)来强制require()回调函数在执行以前等待DOM Ready。当用做loader plugin时,domReady会返回当前的document:
注意:若是document须要一段时间来加载(也许是由于页面较大,或加载了较大的js脚本阻塞了DOM计算),使用domReady做为loader plugin可能会致使RequireJS“超时”错。若是这是个问题,则考虑增长waitSeconds配置项的值,或在require()使用domReady()调用(将其当作是一个模块)。
§ 5.3define I18N bundle
一旦你的web app达到必定的规模和流行度,提供本地化的接口和信息是十分有用的,但实现一个扩展良好的本地化方案又是很繁贅的。RequireJS容许你先仅配置一个含有本地化信息的基本模块,而不须要将全部的本地化信息都预先建立起来。后面能够将这些本地化相关的变化以值对的形式慢慢加入到本地化文件中。
i18n.js插件提供i18n bundle支持。在模块或依赖使用了i18n!前缀的形式(详见下)时它会自动加载。下载该插件并将其放置于你app主JS文件的同目录下。
将一个文件放置于一个名叫“nls”的目录内来定义一个bundle——i18n插件当看到一个模块名字含有“nls”时会认为它是一个i18n bundle。名称中的“nls”标记告诉i18n插件本地化目录(它们应当是nls目录的直接子目录)的查找位置。若是你想要为你的“my”模块集提供颜色名的bundle,应像下面这样建立目录结构:
my/nls/colors.js
该文件的内容应该是:
以一个含有“root”属性的object直接量来定义该模块。这就是为往后启用本地化所需的所有工做。你能够在另外一个模块中,如my/lamps.js中使用上述模块:
my/lamps模块具有一个“testMessage”属性,它使用了colors.red来显示红色的本地化值。
往后,当你想要为文件再增长一个特定的翻译,如fr-fr,能够改变my/nls/colors内容以下:
而后再定义一个my/nls/fr-fr/colors.js文件,含有以下内容:
RequireJS会使用浏览器的navigator.language或navigator.userLanguage属性来断定my/nls/colors的本地化值,所以你的app不须要更改。若是你想指定一个本地化方式,你可以使用模块配置将该方式传递给插件:
注意 RequireJS老是使用小写版本的locale值来避免大小写问题,所以磁盘上i18n的全部目录和文件都应使用小写的本地化值。 RequireJS有足够智能去选取合适的本地化bundle,使其尽可能接近my/nls/colors提供的那一个。例如,若是locale值时“en-us”,则会使用“root” bundle。若是locale值是“fr-fr-paris”,则会使用“fr-fr” bundle。
RequireJS也会将bundle合理组合,例如,若french bundle以下定义(忽略red的值):
则会应用“root”下的red值。全部的locale组件是如此。若是以下的全部bundle都已定义,则RequireJS会按照以下的优先级顺序(最顶的最优先)应用值:
my/nls/fr-fr-paris/colors.js
my/nls/fr-fr/colors.js
my/nls/fr/colors.js
my/nls/colors.js
若是你不在模块的顶层中包含root bundle,你可像一个常规的locale bundle那样定义它。这种情形下顶层模块应以下:
root bundle应看起来以下: