Зачем использовать альтернативный requirejs define: define (function (require) {…}

Я видел, как люди используют альтернативное определение "синтаксиса" в require js, чем то, что описано в документации require js или во многих учебниках.

на обычно определяют "синтаксис":

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

на альтернативное определение "синтаксис":

<script data-main="app/config" src="assets/js/libs/require.js"></script>

file: config.js:

require.config({
   paths: {
      jquery:      '../assets/js/libs/jquery'
   }
});
require(['app']);
: приложение.js:
define(function(require) {
     var FirstModule = require('modules/first');
     //Module code with a dependency on module/first goes here.

каковы преимущества и недостатки использования этого альтернативного "синтаксис"?

1 ответов


Я думаю, что ваше объяснение немного вводит в заблуждение: в обоих случаях у вас будет верхний уровень require вызов data-main атрибут, указывающий файл для запуска процесса требования различных модулей.

так что обычно у вас будет это в вашем HTML:

<script data-main="app/config" src="assets/js/libs/require.js"></script>

затем, в обоих случаях, у вас будет файл app/config который устанавливает вашу конфигурацию (хотя вы можете сделать это непосредственно в HTML) и, что более важно, вызывает require on модули:

require.config({
  paths: {
    jquery:      '../assets/js/libs/jquery'
  }
});
require(['app']);

теперь, когда мы переходим к определению модулей с зависимостями, эти стили отличаются. В стиле amd вы передаете в модуле имена (пути) как массив, так и функцию, которая принимает одинаковое количество аргументов:

app.js

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

в упрощенном синтаксисе CommonJS вы просто передаете require на define и после этого требуйте все модули вам inline:

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

}

возвращаясь к вашему первоначальному вопросу, преимущества стиля CommonJS над стилем amd должны быть ясны.

во-первых, с обычным синтаксисом, если требуется много модулей, это очень легко ошибочно назначать модули неправильным именам переменных. Рассмотрим этот распространенный случай:

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

сразу, вы можете увидеть это, когда мы добавим новый модуль к этому списку, мы должны быть очень осторожны, чтобы соответствующий новый аргумент функции появился в нужном месте, иначе мы можем назначить jQuery Backbone, etc. В некоторых случаях это может создать очень тонкие ошибки, которые трудно отследить.

Теперь рассмотрим синтаксис 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');
  // ...
}

внимание:

  1. сопряжение модуля с именем переменной очень ясно.
  2. порядок операторов require не является важно, поскольку имена переменных спариваются отдельно, а не как сопоставление между массивом и функцией.
  3. модули не должны быть назначены в первую очередь. Они могут быть назначены в любом месте, пока это до того, как модуль фактически используется.

это всего лишь несколько причин, которые приходят на ум, я уверен, что есть и другие. В принципе, если у вас есть только одна или две зависимости, любой синтаксис будет в порядке. Но если у вас сложная сеть модулей зависимости, синтаксис CommonJS, вероятно, предпочтительнее.

обратите внимание, что в документах RequireJS они упоминают это небольшое предостережение:

не все браузеры дают полезную функцию.прототип.метод toString() результаты. По состоянию на октябрь 2011 года мобильные браузеры PS 3 и более старых Opera не работают. Эти браузеры, скорее всего, нуждаются в оптимизированной сборке модулей для ограничений сети/устройства, поэтому просто сделайте сборку с оптимизатором, который знает, как конвертировать эти файлы в нормализованной форме массива зависимостей, как RequireJS optimizer.

но это не главная проблема:

поскольку количество браузеров, которые не могут поддерживать это сканирование toString (), очень мало, безопасно использовать эти подслащенные формы для всех ваших модулей, особенно если вам нравится выстраивать имена зависимостей с переменными, которые будут содержать их значения модулей.