Dojo AMD: No se puede llamar a una función dentro de un requisito
-
09-12-2019 - |
Pregunta
Soy realmente un novato para Dojo, pero como comencé a desarrollar una nueva aplicación con Dojo Versión 1.7.2 También quería usar la nueva sintaxis de AMD para funciones. Lamentablemente no parece que lo consigo. :-(
Lo que más me molesta es que no puedo simplemente llamar a ninguna función que esté dentro de un bloque "Requerir". Por ejemplo, tengo una página que, en la apertura, crea una tabla dinámica con varios widgets en cada fila. Luego tengo un botón que agrega una fila vacía cada vez presionada.
Sin sintaxis AMD, sería fácil:
- Ponga todo mi "Dojo.Require ()" en la cabeza
- y luego cree un montón de mis propias funciones para crear la tabla y los widgets
- La función de agregar fila podría acceder fácilmente a cualquier variable global, mi función anterior se llenó
Pero con AMD es así:
Función inicial crea la tabla y los widgets:
function fillReportTable(repId) {
require(["dojo/dom-construct", "dojo/dom-attr", "dijit/form/FilteringSelect",
"dojo/data/ItemFileReadStore", "dijit/form/ComboBox", "dijit/form/DateTextBox", "dijit/form/Select", "dojo/store/Memory"],
function (domConstruct, domAttr, FilteringSelect, ItemFileReadStore, ComboBox, DateTextBox, Select, Memory) {
// a lot of code to create the table, consisting of SEVERAL functions
function createNewRow(tbl) { ...}
function function1 () {... }
function function2 () {... }
function function3 () {... }
}
Ahora, el botón "Agregar fila vacía" llama a su propia función "addemptyrow".
Pero en esta función tengo que:
- Haga otra necesidad para cada módulo DOJO-MÓDULO
- No puedo usar ninguna de las funciones que están "dentro" de la función "FillReportTetable". Por ejemplo, el "CreateNeWrow" -Function
function addEmptyRow() {
require(["dojo/dom-construct", "dojo/dom-attr", "dijit/form/FilteringSelect",
"dojo/data/ItemFileReadStore", "dijit/form/ComboBox", "dijit/form/DateTextBox", "dijit/form/Select", "dojo/store/Memory"],
function (domConstruct, domAttr, FilteringSelect, ItemFileReadStore, ComboBox, DateTextBox, Select, Memory) {
// a lot of code to create the table, consisting of SEVERAL functions
}
Todo esto parece estar tan complicado con AMD.
¿O falta algo obvio aquí?
Con AMD, si separa su código en muchas funciones pequeñas, ¿realiza el "Requerir" dentro de cada función de nuevo? ¿O pones todas las funciones dentro de un "Requerir" con la lista completa?
Si lo hace la segunda forma, ¿cómo puede llamar a estas funciones de los eventos del widget?
Solución
The easiest way would be to define your own module. Take a look at this tutorial first:
http://dojotoolkit.org/documentation/tutorials/1.7/modules/
Now define your own module, e.g. "./js/mymodules/mymodule.js" (relative to HTML page):
define([
"dojo/dom-construct",
"dojo/dom-attr",
"dijit/form/FilteringSelect",
"dojo/data/ItemFileReadStore",
"dijit/form/ComboBox",
"dijit/form/DateTextBox",
"dijit/form/Select",
"dojo/store/Memory"
], function (domConstruct, domAttr, FilteringSelect, ItemFileReadStore, ComboBox, DateTextBox, Select, Memory) {
function fillReportTable(repId) {
// a lot of code to create the table, consisting of SEVERAL functions
function createNewRow(tbl) { ...}
function function1 () {... }
function function2 () {... }
function function3 () {... }
}
function addEmptyRow() {
// a lot of code to create the table, consisting of SEVERAL functions
}
// Return an object that exposes two functions
return {
fillReportTable: fillReportTable,
addEmptyRow: addEmptyRow
}
});
And use your module like this:
<html>
<head>
<script>
var dojoConfig = {
baseUrl: "./js/",
packages: [
{ name: "dojo", location: "lib/dojo" },
{ name: "dijit", location: "lib/dijit" },
{ name: "dojox", location: "lib/dojox" }
]
};
</script>
<script data-dojo-config="async: true" src="js/lib/dojo/dojo.js"></script>
</head>
...
<script>
require([
"mymodules/mymodule"
], function (mymodule) {
mymodule.fillReportTable(...);
mymodule.addEmptyRow(...);
});
</script>
Otros consejos
Try this:
require([...], function() {
var myFunctions = dojo.getObject('myFunctions', true);
myFunctions.createNewRow = function(...) {
...
};
});
You can now call your functions from anywhere by using
myFunctions.createNewRow();
If you don't want 'myFunctions', you could do
require([...], function() {
var createNewRow = function(...) {};
dojo.setObject('createNewRow', createNewRow);
});
Paul Grime gave you a good example, so I'm just sharing some thoughts.
You don't define all the modules in each function, that's a huge waste of space. Although, even if you try to load a module multiple times, Dojo will only load it once anyway.
This is a simplified module from my latest project, with quite meaningless functionality:
//app module in 'my' folder
define(
[
'app/elements',
'dojo/query',
'dojo/on',
'dojo/fx',
'dojo/_base/fx',
'dojo/dom-construct',
'dojo/_base/event'
//and so on.....
],
function(elements, q, on, fx, baseFx, constr, event)
{
return {
init : function()
{
var node = q(elements.loading);
this.removeNode(node);
this.addEvents();
},
removeNode : function(node)
{
node.remove();
},
addEvents : function()
{
$(elements.buttons).on('click', function(e)
{
alert(q(e).attr('id') + ' was clicked!');
});
}
}
}
Then I get the module by using
define(
[
'my/app',
],
function (app)
{
app.init();
}