Вызов методов в модулях 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(...)?

4 ответа

Решение

Одним из преимуществ использования 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

<input type="button" onclick="(function() { require('mymodule').do_work() })()"/>
Другие вопросы по тегам