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

Каков предпочтительный метод передачи данных сервера в модуль RequireJS?

Есть ли предпочтительный способ передачи данных сервера в модуле 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
        }
    }
});
4b9b3361

Ответ 1

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

Два подхода

В общем, есть два способа обойти это.

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

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

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

Это зависит от личных предпочтений и от того, сколько у вас этих "дао". Если у вас более одного, это может стать политикой, так как вам нужен новый параметр для каждого модуля dao. В этом случае сделать их глобальными кажется более чистыми.

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

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

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

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

Ответ 2

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

<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

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

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

Честно говоря, я просто позвоню AJAX.

Ответ 4

Использовать глобальную переменную окна для передачи данных сервера в приложение 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
});

Ответ 5

Я только начал сегодня с 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 выполнить модуль, как только будут загружены require.js и все модули. Опуская его (модуль) и просто определяя его как встроенный модуль, я могу использовать переменные PHP.

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

Ответ 6

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

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

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 для загрузки приложения, без явного вызова требовать, может работать, но из-за состояния гонки. Если определение dto по какой-то причине займет больше, чем требуется, то requirejs для вызова основного модуля script приведет к сбою. Мы не хотим полагаться на это, поэтому делаем все сами:)

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

<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>