Методы вызова в модулях RequireJs из HTML-элементов, таких как onclick-обработчики

Я меняю проект из "старой" структуры структуры браузера в "новую" структуру браузера или -сервера на стороне javascript с помощью require.js.

На клиенте я использую jQuery, размещенную на удаленном сервере, поэтому я начал с примера, который они приводят в использовании конфигурации приоритета для README:

<title>My Page</title>
<script src="scripts/require.js"></script>
<script>
require({
    baseUrl: 'scripts',
    paths: {
        jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min',
        jqueryui: ...,
        ...
        ... // bunch more paths here
    },
    priority: ['jquery']
}, [ 'main' ]);
</script>

Это действительно работает. Но я бы хотел экспортировать функциональность с главной страницы на веб-страницу HTML. Например:

<a class="button" href="#" onclick="MyApi.foo();">
    <img src="foo.png" alt="foo" />Click for: <b>Foo!</b>
</a>

Прежде чем приступать к шаблону модуля AMD, я бы раскрыл функциональность из своих различных файлов, создав объект словаря в глобальном пространстве:

// main.js

var MyApi = {};

jQuery(document).ready(function($) {
    // ...unexported code goes here...

    // export function via MyApi
    MyApi.foo = function() {
        alert("Foo!");
    };
});

Но я не знаю, каков правильный подход в require.js. Можно ли вставлять в HTML более теги require внутри тегов <script>, а затем называть модули так, чтобы их можно было использовать с веб-страницы? Или это всегда должно выполняться динамически внутри main.js, например $('#foobutton').click(...)?

Ответ 1

Одним из преимуществ использования AMD является снижение потребности в пространствах имен. Попытка создать их снова с RequireJS будет идти против моделей, которые AMD продвигает.

Что касается использования main.js, это действительно реально, если у вас есть одностраничное приложение, а весь код - ссылкой с одного места. Вы можете делать дополнительные звонки, чтобы требовать и загружать другие модули по мере необходимости.

Используя ваш пример сверху, вы можете приблизиться к нему следующим образом:

foo.js

define(['jquery'], function($) {

    // Some set up 
    // code here

    // Return module with methods
    return {
        bar: function() {

        }
    }


});

page.js

require(['foo'], function(foo) {

    // jQuery loaded by foo module so free to use it
    $('.button').on('click', function(e) {
        foo.bar();
        e.preventDefault();
    });

});

Затем в вашей странице запросите файл page.js с требованием.

Используя приведенный выше пример:

require({
    // config stuff here
}, [ 'page' ]);

Или загрузите его на страницу ниже:

<script>
    require(['page']);
</script>

Некоторые дополнительные точки

  • Используя вышеприведенный шаблон, page.js может легко потребовать много других модули для загрузки других функций, связанных с страницей.

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

  • Использование этого способа для присоединения событий к вашим элементам DOM будет скорее всего полагаться на модуль DOM Ready, предоставленный RequireJS

Ответ 2

Вы также можете установить ссылку на класс окна javascript.

В нижней части модуля приложения window.MyApi = MyApi;

<a class="button" href="#" onclick="MyApi.foo();"></a>

Ответ 3

размещение onclick="" внутри вашей разметки кажется грязным - смешивание презентации с контентом. Я бы порекомендовал вам добавить блок <script> и поместить в него require и один раз внутри обратного вызова и внутри другого внутреннего $(document).ready(), если необходимо, подключите обработчики событий обычным способом: $('#node').click(...). Если вы можете сделать это в целом достаточно, чтобы оно применимо к нескольким страницам, тогда помещайте его во внешний файл, который минимизируется, комбинируется и кэшируется. Но обычно эти вещи становятся специфичными для страниц, поэтому тег <script> в нижней части страницы является хорошим решением, чтобы избежать очередного запроса внешнего ресурса.

Ответ 4

Другое решение - просто использовать такой код (конечно, requirejs должен быть добавлен на страницу):

<input type="button" onclick="(function() { require('mymodule').do_work() })()"/>