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

时间:2011-10-20 11:16:57

标签: 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 */ 
}) 

但我发现这令人困惑,因为我认为如果一个模块具有依赖性,那么它们应该通过主define([dependancies], fnDefinition)函数传递,而不是通过require()传递给它,如上例所示做。

这背后有理由吗?

1 个答案:

答案 0 :(得分: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 */ 
}); 

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


使用本地require的原因:

  1. 由于运行时条件,您不知道在构建时(或加载时)需要哪些模块
  2. 您明确希望在需要之前推迟加载某些模块
  3. 你想根据特征检测的结果加载一个模块的变体(尽管像dojo的“has!”插件可能是一个更好的解决方案(对不起,链接不包括我))。
  4. 最后,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 */ 
    }); 
    

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

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