javascript - browserify
¿Cuál es el método preferido para pasar datos del servidor a un módulo RequireJS? (6)
Acabo de comenzar hoy con RequireJS
y antes de esto estaba acostumbrado a llamar a la función que quería ejecutar en la carga de la página de esta manera:
<script>
my_method(<?php echo json_encode( array(''opt1''=>true, ''opt2''=>false) );?>);
</script>
Como @ ziad-saab, encontré que lo más parecido que puedo hacer es no usar el atributo data-main
y simplemente definir un módulo en línea:
<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>
El atributo data-main
le RequireJS
a RequireJS
que ejecute el módulo tan pronto como require.js y se carguen todas las dependencias del módulo. Omitiéndolo (el módulo) y definiéndolo simplemente como un módulo en línea, puedo PHP
variables de PHP
.
De esta manera, no necesito manejar los módulos que contienen mis configuraciones y la transición para usar requirejs es más fácil en mi entorno.
¿Hay alguna forma preferida de pasar los datos del servidor en un módulo RequireJS? Nuestra implementación actual se parece a los siguientes fragmentos de código; usando un objeto ''page'' para guardar cualquier servidor / datos dinámicos y pasarlo a la rutina de arranque principal. (No queremos utilizar ajax para completar ninguna dependencia en este momento)
Desde una página de servidor:
<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
}
}
});
He encontrado algunas de las respuestas confusas, así que aquí están los pasos exactos que debe seguir para que funcione:
En mi caso lo estoy haciendo así:
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'']);
some-module.js
(en este caso layout.js que se requiere en app / bootstrap)
"use strict";
define([
''dto'',
''jquery'',
''lodash''
], function (dto, $, _) {
console.log(dto);
});
Tenga en cuenta que el uso de data-main
para arrancar la aplicación, sin necesidad de una llamada explícita, podría funcionar, pero debido a una condición de carrera. Si la definición de dto por algún motivo llevaría más de lo necesario, se requerirá que los requisitos para llamar al script del módulo principal se bloqueen. No queremos confiar en eso, así que hacemos todo nosotros mismos :)
Así que esto no funcionaría (a veces):
<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>
RequireJS no dice nada sobre cómo tratar con los datos del servidor, ya que es un medio para modular su javascript. Así que, en ese sentido, no hay un estándar de facto y puedes combinar RequireJS con json, ajax, php, xml incrustado, etc. como quieras.
Dos enfoques
En general, hay dos maneras de hacer esto.
- Modele un módulo ''dao'' o ''servicio'' que obtiene los datos requeridos del servidor y los hace accesibles a sus usuarios (similar a su enfoque actual, vea el ejemplo de código a continuación)
- Defina un objeto global al que tengan acceso todos los módulos.
El primer enfoque agrega parámetros a sus funciones.
El segundo proporciona acceso global. Esto también requiere su propio código de inicialización para comenzar a buscar datos.
Todo se reduce a las preferencias personales y cuántos de estos ''dao''s'' tienes. Si tiene más de uno, podría volverse contaminante, ya que necesita un nuevo parámetro para cada módulo dao. En ese caso, hacerlos globales parece más limpio.
Un problema con su enfoque.
Sin embargo, hay un problema con su enfoque actual, donde tiene el módulo de página como una definición (usando define()
lugar de require()
), porque se crea un módulo de definición para cada objeto que depende de él. Esto significa potencialmente múltiples llamadas dentro de la misma página. En su lugar, utilice:
// in seperate file page.js:
require([], function () {
return { guid: "<%=Guid.NewGuid() %>" };
});
De esta manera, RequireJS reconoce la página como un módulo porque es un archivo separado y se enviará a su servidor solo una vez por página.
Si tiene un objeto JSON, haga una llamada AJAX como @yves mencionada en los comentarios.
Hay otras opciones si no quieres hacer eso. Podría poner el guid como un atributo de datos en la etiqueta de script. Además, podrías intentar dinamizar el archivo js del cargador para que la configuración esté configurada en eso.
Honestamente, solo haría una llamada AJAX.
Usualmente hago algo como esto (usando PHP en el back-end, pero cualquier cosa funciona):
<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>
Y luego define mi módulo como algo que requiere una configuración:
define([''jquery''], function($) {
var App = function(options) {
this.options = options;
//blabla
}
// add some stuff to App.prototype maybe
// and finally...
return App;
});
Utilice la variable global de ventana para transferir datos del servidor a la aplicación 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>
en 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
});