为什么使用备用requirejs定义:define(function(require){...}

joh*_*olo 19 requirejs

我已经看到人们在require js中使用替代定义"语法",而不是在require js'文档或许多教程中描述的.

通常的定义"语法":

define(['module/first'], function (firstModule) {
   //Module code with a dependency on module/first goes here.
});
Run Code Online (Sandbox Code Playgroud)

备用定义"语法":

<script data-main="app/config" src="assets/js/libs/require.js"></script>
Run Code Online (Sandbox Code Playgroud)

file:config.js:

require.config({
   paths: {
      jquery:      '../assets/js/libs/jquery'
   }
});
require(['app']);
Run Code Online (Sandbox Code Playgroud)

file:app.js:

define(function(require) {
     var FirstModule = require('modules/first');
     //Module code with a dependency on module/first goes here.
Run Code Online (Sandbox Code Playgroud)

使用这种替代"语法"有哪些优点和缺点?

Chr*_*erg 41

我认为你的解释有点误导:在这两种情况下,你都会有一个require带有data-main属性的顶级调用,指定一个文件来启动需要不同模块的过程.

通常,您将在HTML中使用此功能:

<script data-main="app/config" src="assets/js/libs/require.js"></script>
Run Code Online (Sandbox Code Playgroud)

然后,在这两种情况下,您将拥有一个app/config设置配置的文件(尽管您可以直接在HTML中执行此操作),更重要的是调用require模块:

require.config({
  paths: {
    jquery:      '../assets/js/libs/jquery'
  }
});
require(['app']);
Run Code Online (Sandbox Code Playgroud)

现在,我们开始定义具有这些样式不同的依赖项的模块.在amd样式中,您将模块名称(路径)作为数组传递,并使用相同数量的参数传递一个函数:

app.js

define(['module/first', 'module/second', 'module/third'], function (firstModule, secondModule, thirdModule) {
  // use firstModule, secondModule, thirdModule here
});
Run Code Online (Sandbox Code Playgroud)

在简化的语法CommonJS的,你只是传递requiredefine,然后要求你需要什么内嵌模块:

app.js

define(function(require) {
  var firstModule = require('modules/first');
  var secondModule = require('modules/second');
  var thirdModule = require('modules/third');
  // use firstModule, secondModule, thirdModule here

}
Run Code Online (Sandbox Code Playgroud)

回到原来的问题,CommonJS风格优于amd风格的优势应该是清楚的.

首先,使用传统语法,如果需要许多模块,则容易错误地将模块分配给错误的变量名称.考虑这种常见情况:

define(['jquery', 'underscore', 'backbone', 'modules/first', 'modules/second', 'modules/third', 'i18n', 'someOtherModule'], function ($, _, Backbone, first, second, third, I18n, someOtherModule) {
  // ...
});
Run Code Online (Sandbox Code Playgroud)

马上,你可以看到当我们在这个列表中添加一个新模块时,我们必须非常小心相应的新函数参数出现在正确的位置,否则我们可以将jQuery分配给Backbone,等等.在某些情况下,这个可以创建非常微妙的错误,很难追查.

现在考虑CommonJS语法:

define(function(require) {
  var $ = require('jquery');
  var _ = require('underscore');
  var Backbone = require('backbone');
  var firstModule = require('modules/first');
  var secondModule = require('modules/second');
  var thirdModule = require('modules/third');
  var I18n = require('i18n');
  var someOtherModule = require('someOtherModule');
  // ...
}
Run Code Online (Sandbox Code Playgroud)

注意:

  1. 模块与变量名称的配对非常清楚.
  2. require语句的顺序并不重要,因为变量名称是单独配对而不是数组和函数之间的映射.
  3. 不需要先分配模块.它们可以分配到任何地方,只要它在实际使用模块之前.

这些只是我想到的几个原因,我相信还有其他原因.基本上,如果你只有一个或两个依赖项,任何一种语法都可以.但是如果你有一个复杂的模块依赖关系网络,那么CommonJS语法可能更可取.

请注意,在RequireJS文档中,他们提到了这个小警告:

并非所有浏览器都提供可用的Function.prototype.toString()结果.截至2011年10月,PS 3和较旧的Opera Mobile浏览器没有.这些浏览器更可能需要针对网络/设备限制的模块的优化构建,因此只需使用优化器进行构建,该优化器知道如何将这些文件转换为规范化的依赖关系数组形式,如RequireJS优化器.

但这不是一个主要问题:

由于不能支持此toString()扫描的浏览器数量非常少,因此可以安全地将所有模块用于所有模块,特别是如果您希望将依赖项名称与保存其模块值的变量对齐.

  • 如果只有RequireJS文档如此清晰,这是一个很好的答案. (4认同)