Каков предпочтительный способ передачи данных сервера в модуль RequireJS? - PullRequest
24 голосов
/ 24 мая 2011

Есть ли предпочтительный способ передачи данных сервера в модуле RequireJS?Наша текущая реализация выглядит следующим образом:использование объекта 'page' для хранения любых серверных / динамических данных и их передача в основной загрузчик.(Мы не хотим использовать ajax для заполнения каких-либо зависимостей в настоящее время)

со страницы сервера:

<script data-main="scripts/main" src="scripts/require-jquery.js"></script>
<script type="text/javascript">
  define("page", function () {
      return { guid: "<%=Guid.NewGuid() %>" };
    });
</script>

main.js

require(["jquery", "jquery.alpha", "page"], function ($, alpha, page) {
    alpha.initialize(page);
});

jquery.apha.js

define(["jquery", "page"], function ($, page) {
    return {
        initialize: function () {
            console.log(page.guid);
            //logs guid as expected
        }
    }
});

Ответы [ 6 ]

4 голосов
/ 31 мая 2012

Я обычно делаю что-то вроде этого (использую PHP на серверной части, но все работает):

<script src="scripts/require-jquery.js"></script>
<script>
require(['scripts/main'], function(App) {
  var myApp = new App({
    param1: <?=json_encode($param1);?>,
    param2: <?=json_encode($param2);?>
  });
});
</script>

А затем определяю мой модуль как нечто, принимающее конфигурацию:

define(['jquery'], function($) {
  var App = function(options) {
    this.options = options;
    //blabla
  }

  // add some stuff to App.prototype maybe

  // and finally...
  return App;
});
3 голосов
/ 30 мая 2012

RequireJS ничего не говорит о том, как обращаться с данными сервера, поскольку это средство для модуляции вашего javascript. Таким образом, в этом отношении не существует стандарта де-факто, и вы можете комбинировать RequireJS с json, ajax, php, внедренным xml и т. Д. По своему усмотрению.

Два подхода

Обычно есть два способа сделать это.

  1. Смоделируйте модуль 'dao' или 'service', который получает необходимые данные с сервера и делает его доступным для пользователей (аналогично вашему текущему подходу, см. пример кода ниже)
  2. Определить глобальный объект, к которому все модули имеют доступ

Подход first добавляет параметры в ваши функции.

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

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

Проблема с вашим подходом

Однако существует проблема с вашим текущим подходом, когда у вас есть модуль Page в качестве определения (используется define() вместо require()), потому что для каждого объекта, который зависит от него, создается определяющий модуль. Это потенциально означает несколько вызовов на одной странице. Вместо этого используйте:

// in seperate file page.js:
require([], function () {
  return { guid: "<%=Guid.NewGuid() %>" };
});

Таким образом RequireJS распознает страницу как модуль, потому что это отдельный файл, и он попадает на ваш сервер только один раз на страницу.

1 голос
/ 30 апреля 2012

Если у вас есть объект JSON, сделайте AJAX-вызов, такой как @yves, упомянутый в комментариях.

Существуют другие варианты, если вы не хотите этого делать.Вы можете поместить guid в качестве атрибута данных в тег скрипта.Кроме того, вы можете попробовать сделать динамический js-файл загрузчика, чтобы в нем была задана конфигурация.

Честно говоря, я бы просто сделал вызов AJAX.

0 голосов
/ 31 августа 2017

Я нашел некоторые ответы запутанными, поэтому вот точные шаги, которые вы должны выполнить, чтобы это сработало для вас:

В моем случае я делаю это так:

index.php

<script src="/js/crm/lib/require.js"></script>
<script>
    // this is so called "named define"
    define('dto', {
        page: JSON.parse('{{ pageDTO | json_encode }}'),
        flashMessages: JSON.parse('{{ this.flashSession.getMessages() | json_encode }}')
    });
    // note we are using relative path to public dir here
    // order is also important, we need to define our dto module before bootstraping the application
    require(['/js/crm/app.js']);
</script>

app.js

"use strict";

require.config({
    // ...
    baseUrl: '/js/crm/lib',
    paths: { app: '../app' }
});

require(['app/bootstrap']);

некоторые-module.js

(в данном случае layout.js, который требуется в app / bootstrap)

"use strict";

define([
    'dto',
    'jquery',
    'lodash'
], function (dto, $, _) { 
    console.log(dto);
});

Примечание с использованием data-main для начальной загрузки приложения, без явного вызова require может работать, но из-за состояния гонки. Если определение dto по какой-либо причине потребует больше, чем требует requirejs для вызова сценария основного модуля, произойдет сбой. Мы не хотим на это полагаться, поэтому все делаем сами:)

Так что это не сработает (иногда):

<script data-main="/js/crm/app.js" src="/js/crm/lib/require.js"></script>
<script>
    // this is so called "named define"
    define('dto', {
        page: JSON.parse('{{ pageDTO | json_encode }}'),
        flashMessages: JSON.parse('{{ this.flashSession.getMessages() | json_encode }}')
    });
</script>
0 голосов
/ 03 октября 2013

Я только сегодня начал с RequireJS, а до этого меня просто вызывали функцию, которую я хотел выполнить при загрузке страницы, следующим образом:

<script>
my_method(<?php echo json_encode( array('opt1'=>true, 'opt2'=>false) );?>);
</script>

Как @ ziad-saab, яобнаружил, что самое похожее, что я могу сделать, - это не использовать атрибут data-main, а просто определить встроенный модуль:

<script src="path/to/require.js"></script>
<script>
require(['my/module'],function(module){
    module.my_method(<?php echo json_encode( array('opt1'=>true, 'opt2'=>false) );?>); 
});
</script>

Атрибут data-main указывает RequireJS выполнить модуль, как только потребуется.js и все зависимости модуля загружены.Пропустив его (модуль) и просто определив его как встроенный модуль, я могу добавить PHP переменные.

Таким образом, мне не нужно работать с модулями, которые содержат мои конфигурации и переходиспользовать requirejs проще в моей среде.

0 голосов
/ 20 сентября 2013

Используйте глобальную переменную окна для передачи данных сервера в приложение js:

 <script type="text/javascript">
    window.server_data=parseJSON(<?php echo json_encode(array ("server_data"=>"it works!"));?>);
 </script>
 <script data-main="js/application" src="js/lib/require.js"></script>

в application.js:

requirejs(["app/main"],function (MyApp){
     console.dir(window.server_data); //all our application need this global variable
    var myApp=new MyApp();
    myApp.init(window.server_data); //and your application now has server data
});
...