Подтвердить что ты не робот

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

Я видел, как люди используют альтернативный синтаксис define в 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']);

file: app.js:

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

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

4b9b3361

Ответ 1

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

Как правило, вы будете иметь это в своем HTML:

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

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

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, а затем требуете, какие модули вам нужны:

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, и т.д. В некоторых случаях это может создать очень тонкие ошибки, которые трудно отследить.

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

Обратите внимание, что:

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

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

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

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

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

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