使用AMD模块,何时(或为什么)可以在define()中使用require()?

Int*_*ist 19 requirejs js-amd curljs

我对AMD模块的理解(使用例如RequireJs或curl.js)是:

require() 用于异步加载不同的模块,加载后执行回调fn.

要定义模块,您可以使用单独的脚本 define()

但我已经看到一些模块require()在其函数定义中使用,例如

define([a, b, c], function(i, ii, iii){ 
    require([d, e, f], function(d, e, f) {
        // do some stuff with these require()'d dependancies
    })
    /* rest of the code for this module */ 
}) 
Run Code Online (Sandbox Code Playgroud)

但我发现这令人困惑,因为我认为如果一个模块具有依赖性,那么它们应该通过main define([dependancies], fnDefinition)函数传递,而不是通过require()上面的例子来实现.

这背后有理由吗?

uns*_*ble 28

您可能希望require()在模块中使用几个原因.

但首先,请务必请求引用正确的require变量.在您的示例中,引用require全局的.您希望引用一个require范围为模块上下文的引用(有时称为"本地需求").这很简单:

define(["a", "b", "c", "require"], function(i, ii, iii, require){ 
    require(["d", "e", "f"], function(moduleD, moduleE, moduleF) {
        // do some stuff with these require()'d dependencies
    })
    /* rest of the code for this module */ 
}); 
Run Code Online (Sandbox Code Playgroud)

这一点很重要的主要原因是确保正确解析相关模块ID(例如"./peerModule"或"../unclePath/cousinModule").(这是其中一个原因,curl.js require默认没有全局.)


使用本地的原因require:

  1. 由于运行时条件,您不知道在构建时(或加载时)需要哪些模块
  2. 您明确希望延迟加载某些模块,直到需要它们为止
  3. 你想根据特征检测的结果加载一个模块的变体(虽然像dojo的"有!"插件可能是一个更好的解决方案(对不起,链接躲避我))

最后,AMD定义了require与CommonJS Modules/1.1中创作的模块兼容的第二种用法,然后将其包装在一个define.这些看起来像这样:

define(function(require, exports, module){ 
    var a = require("pkgZ/moduleA"), // dependency
        b = require("pkgZ/moduleB"); // dependency
    /* rest of the code for this module */ 
}); 
Run Code Online (Sandbox Code Playgroud)

服务器端的JavaScript开发人员可能会觉得这种格式很吸引人.:)

一些AMD加载器(例如RequireJS 0.2 +,dojo 1.7 +,bdLoad和curl.js 0.6+)将检测这种混合AMD/CJSM1.1格式,并通过扫描模块进行require调用来查找依赖关系.