2012-03-08 11 views
13

Sono davvero un principiante del dojo ma come ho iniziato a sviluppare una nuova applicazione con dojo versione 1.7.2 volevo anche usare la nuova sintassi AMD per le funzioni. Sfortunatamente non sembra averlo capito. :-(Dojo AMD: impossibile chiamare una funzione all'interno di un fabbisogno

Quello che mi infastidisce di più è che non posso semplicemente chiamare qualsiasi funzione che si trova all'interno di un -block "richiedono". Per esempio io ho una pagina, che in apertura crea una tabella dinamica con diversi widget in .. ogni riga poi ho un pulsante che aggiunge una riga vuota ogni volta premuto

Senza AMD sintassi sarebbe facile:
- messo tutto il mio "dojo.require()" nel HEAD
- e quindi creare un sacco di mie funzioni per creare la tabella e i widget
- la funzione aggiungi riga potrebbe facilmente accedere a qualsiasi variabile globale la mia funzione precedente zione riempito

Ma con AMD la sua in questo modo:

funzione iniziale crea la tabella e widget:

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() {... } 
} 

Ora il pulsante "Add Empty Row" chiama la sua funzione "addEmptyRow".
Ma in questa funzione devo:
- fare un altro richiede per ogni dojo modulo nuovo
- non posso utilizzare una delle funzioni che sono "dentro" del -funzione "fillReportTable". Ad esempio, il "createNewRow" -funzione

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 
} 

Tutto questo sembra essere così tanto complicato con AMD.
O mi manca qualcosa di ovvio qui?
Con AMD se si separa il proprio codice in molte piccole funzioni, si esegue nuovamente il "require" all'interno di EACH? O metti tutte le funzioni all'interno di uno "richiedi" con l'elenco completo?
Se lo fai nel secondo modo, come puoi chiamare queste funzioni dagli eventi del widget?

risposta

11

Il modo più semplice sarebbe definire il proprio modulo. Date un'occhiata a questo tutorial prima:

http://dojotoolkit.org/documentation/tutorials/1.7/modules/

Ora definire il proprio modulo, per esempio "./js/mymodules/mymodule.js" (relativi alla pagina HTML):

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 
    } 

}); 

e utilizzare il modulo come questo:

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

così, 'fillReportTable: fillReportTable' nell'oggetto ritorno esporterà la funzione 'fillReportTable()'? – joakimdahlstrom

+0

Sì, è vero. Quando il modulo * mymodule * è 'require'd, il caricatore AMD carica un particolare file JS per quel modulo (nel nostro caso 'mymodules/mymodule.js'. All'interno di quel file JS si passa una funzione a' define', e questa funzione è usata per "esportare" le funzionalità del modulo.Nel tuo caso, il modulo rappresenta un oggetto che ha due funzioni di supporto –

+0

Quindi ora posso chiamare mymodule.fillReportTable() da qualsiasi luogo al di fuori della richiesta? – Andy

4

Prova questo:

require([...], function() { 
    var myFunctions = dojo.getObject('myFunctions', true); 
    myFunctions.createNewRow = function(...) { 
     ... 
    }; 
}); 

È ora possibile richiamare le funzioni da qualsiasi luogo utilizzando

myFunctions.createNewRow(); 

Se non si vuole 'myfunctions', si potrebbe fare

require([...], function() { 
    var createNewRow = function(...) {}; 

    dojo.setObject('createNewRow', createNewRow); 
}); 
3

Paul Grime ti ha dato un buon esempio, così ho' Sto solo condividendo alcuni pensieri.

Non si definiscono tutti i moduli in ogni funzione, si tratta di un enorme spreco di spazio. Sebbene, anche se provi a caricare un modulo più volte, Dojo lo caricherà solo una volta.

Questo è un modulo semplificato dal mio ultimo progetto, con funzionalità del tutto priva di significato:

//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!'); 
      }); 
     } 
    } 
} 

allora ottengo il modulo utilizzando

define(
[ 
    'my/app', 
], 

function (app) 
{ 
    app.init(); 
}