在RequireJS中,require()和define()有什么区别?

35

在RequireJS中,使用require()和define()的基本区别是什么?

require(['a'], function(a) {
    // some code
});

// A.js
define(['b','c','d','e'], function() {
    //some code
});

有任何使用案例将非常有帮助。


请参考https://dev59.com/OWkw5IYBdhLWcg3w_fmK。 - Mark Meyer
1
这是一个重复的问题,但是这里应该通过示例来解释。 - z--
5个回答

53

在早期使用中令我感到困惑的一个核心区别是弄清楚 define 可能永远不会被调用

只要每个文件中只有一个 define,它就会将该模块注册为在该文件名下可用。然而,define 模块只有在一个 require 函数请求时才加载。

定义:如果您需要一个 XXX,则首先加载其他内容,然后返回此函数的结果。

需要:加载其他内容,然后运行此函数(没有“if”)。

示例:假设您将此JS文件包含在您的页面中:

// this is in company/welcomepage.js
define(['company/ui_library'],
    function(uiLib) {
        console.log('Welcome to {company}!');
    }
);

如果这是唯一的Javascript文件,您可以打开页面,尽管脚本告诉它欢迎用户,但控制台日志中将没有任何内容。然而,如果在页面的某处或另一个脚本中插入以下内容,则会发生变化:

require(['company/welcomepage'], function() {
    // optionally insert some other page-initialization logic here
});

现在,页面加载时将在控制台中显示欢迎消息。

实际上,有了第二个位置以后,就不需要手动把welcomepage.js包含为<script>标签了,它会从其位置载入,只要它看到require并意识到需要它。


1
谢谢您的回答...您可以举个基本的例子来详细说明吗? - copenndthagen
1
@Katana314...你能详细说明一下吗? - copenndthagen
1
@testndtv 添加了一个示例,希望能有所帮助。 - Katana314
小细节:由于/company/welcomepage.js声明了对'company/ui_library'的依赖关系,因此将加载的文件是/company/company/ui_library.js--这是您想要的吗? - Don Hatch
在Chrome 57.0.2987.37和RequireJS 2.3.2中,无法重现“如果这是唯一的Javascript文件,则控制台日志中将没有任何内容”的问题。显然,这不可能是唯一的javascript文件;您需要require.js。如果我的HTML代码为<script src="require.js"></script><script src="company/welcomepage.js"></script>,则会出现Uncaught Error: Mismatched anonymous define() module: function (uiLib) { console.log('Welcome to {company}!'); }。如果我的HTML代码为<script data-main="company/welcomepage.js" src="require.js"></script>,则可以看到控制台消息。您能否提供一个完整的示例? - Don Hatch
1
@DonHatch 在第一点上:AMD 可以配置为始终从某个根路径开始,或者将某个文件夹名称识别为具有某个主目录(例如,“jquery”在“apis.google.com/cdn/jquery”中)。在第二个示例中:当我针对 requirejs 2.1.5 或 Dojo 进行测试时,没有出现此错误。如果您是正确的,那么它可能已经改变了行为;也许这是帮助人们尽早发现此类问题而进行的更改。在您的第三个示例(data-main)中,这明确要求该文件,因此它决定运行它。 - Katana314

24

requirerequirejs是一样的。

require === requirejs // true

`require` 是一种加载已定义模块的方法。例如,要加载 `logger` 模块,可以这样做:
require(["logger"], function(logger){
  logger.bla("S");
});

这里我正在调用require,指定一个已经定义的名为logger的模块,并通过调用其bla方法来使用它。

define是定义模块的一种方式。例如,要定义一个logger模块,我可以这样做:

// logger.js
define(function(){
  return {
    bla: function(x){
      alert(x);
    }
  }
});

在这里,我调用了define并定义了logger模块。在这个模块中,我返回了我想要暴露的bla函数。
有时候define看起来非常类似于exports,因为define也可以依赖和使用其他模块,就像require可以使用其他模块一样。让我给你展示同样的logger模块,这次使用一个模块:
// logger.js
define(["popup"], function(popup){
  return {
    bla: function(x){
      popup.show(x);
    }
  }
});

这里是我定义的日志模块,还有一个叫做“popup”的依赖项,因此它看起来像是需要使用“require”。

只有你的评论中提到了“logger”,那么是什么定义了它作为“logger”模块?是注释还是文件名? - Scott
非常好的回答。我已经使用JavaScript编码了几年,相比面向对象编程的Java,我总是觉得它很混乱。您的回答简洁明了,正是我需要听到的,以澄清使用requireJS进行模块化(而不是通常的原始立即调用函数方式)。 - kiwicomb123
1
@Scott 可能已经晚了。实际的 AMD 语法是:define(id?, dependencies?, factory); 如果没有指定模块名称(即 id 参数),则模块名称为其文件位置。 - Advena

1
我相信你总是使用define来定义你的模块。你有几种方式可以这样做,你可以在define的第一个参数中使用一个数组来定义一个带有依赖关系的模块(就像你发布的示例一样)。
或者你可以使用简化的CommonJS包装器,像这样:
define(function (require) {
    var otherModule = require('otherModule');
    return function () {
        return otherModule.operation();
    };
});

也许你会混淆JSONP服务依赖格式,它使用require()来加载服务,然后指定define()作为JSONP回调函数,一旦服务响应,就会定义模块。
因此,最终你使用define()来定义模块,并使用require()来加载它们。

-1

define 是我们声明模块的方式,符合 AMD 模块格式(还有其他可用的模块格式,如 CommonJSES2015System.registerUMD)。

而 ..

require 是一个模块加载构造,可在像 RequireJsSystemJSNode 的内置模块加载器等模块加载器中使用。当您想要使用上述任一模块格式中定义的模块时,就可以使用它。


-4

require()define()都用于加载依赖项。这两种方法之间有一个重大的区别。

非常简单

Require(): 方法用于运行即时功能。 define(): 方法用于定义可在多个位置(重复使用)中使用的模块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接