Методы вызова в модулях 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() })()"/>