Domanda

Attualmente sto sviluppando una nuova applicazione web.

Questa è la prima volta che utilizzo requirejs con i moduli AMD.

Non è così facile abituarsi a quel nuovo paradigma secondo cui non ci sono, a quanto ho capito, variabili nello spazio dei nomi globale.

Nelle precedenti applicazioni web avevo sempre una variabile nello spazio dei nomi globale che potevo utilizzare per condividere diverse risorse tra diversi moduli.

Ora con i moduli AMD requirejs, utilizzo backbone.js e jquery (entrambe le versioni AMD: jquery 1.7.1 e backbone.js 0.5.3-optamd3).

Da qualche parte nella mia applicazione prendo un modulo backbone.js dal server (oggetto utente).Vorrei avere accesso a questo modulo da diversi moduli AMD.Voglio anche avere un oggetto evento a livello di applicazione.

Potresti dirmi:qual è il modo giusto in requirejs AMD di condividere le risorse tra diversi moduli?

È stato utile?

Soluzione

Ho trovato una soluzione da solo.

Grazie, IntoTheVoid, per la tua risposta, ma speravo in una soluzione simile ad AMD.Ciò significa, non ancora una volta, "inquinare" lo spazio dei nomi globale.

C'erano 2 chiavi per la mia soluzione:

"https://github.com/addyosmani/backbone-aura" da Addy Osmani e "https://github.com/amdjs/amdjs-api/wiki/AMD" la specifica API AMD (Asynchronous Module Definition).

Le specifiche dicono:"Se la factory è una funzione, dovrebbe essere eseguita solo una volta."

Pertanto, se un modulo amd viene specificato più volte come dipendenza in un'applicazione web, la dipendenza non è solo NON CARICATO PIÙ VOLTE, è altresì NON ESEGUITO PIÙ VOLTE, e questa è la novità per me.Viene eseguito una sola volta e viene mantenuto il valore restituito dalla funzione factory.Ogni dipendenza con lo stesso percorso ha lo stesso oggetto.E questo cambia tutto.

Quindi, definisci semplicemente il seguente modulo amd:

define([], function() {
    var app_registry = {};
    app_registry.global_event_obj = _.extend({}, Backbone.Events);
    app_registry.models = {};
    return app_registry;
});

Ora, in quei moduli in cui desideri condividere le risorse, dichiari questo modulo app_registry come dipendenza e scrivi in ​​uno:

define(['jquery','underscore','backbone','app_registry'], 
  function ($, _, Backbone, app_registry){
    var firstView = Backbone.View.extend({
    initialize: function() {
        _.bindAll (this, 'methodOne'); 
        this.model.bind ('change', this.methodOne);   
        this.model.fetch();
    },  
    methodOne: function() {
        app_registry.models.abc = this.model;
    }
    ...

e nell'altro:

define(['jquery','underscore','backbone','app_registry'], 
  function ($, _, Backbone, app_registry){
    var secondView = Backbone.View.extend({
    initialize: function() {
       _.bindAll (this, 'methodTwo'); 
        app_registry.global_event_obj.bind ('special', this.methodTwo);
    },  
    methodTwo: function() {
        app_registry. ...
    }
    ...

Altri suggerimenti

Per rispondere alla tua domanda su come fornire un oggetto evento a largo applicazione, è possibile creare un modulo AMD chiamato GlobalContext e istanziarlo in Main.js.
Successivamente è possibile allegare le impostazioni a GlobalContext e utilizzare il contesto globale per creare sottocomponenti ecc.

    //main.js file
    require([ "./global-context" ], function( GlobalContext) {
             new GlobalContext();
    });

Nel file globale-conftext.js possiamo quindi eseguire attività come il caricamento di moduli figlio

    define(["Boiler", "./settings", "./modules/modules"], 
           function (Boiler, settings, modules) {
                  var GlobalContext = function () {

                //here we use a template javascript class called Boiler.Context
                var globalContext = new Boiler.Context("GlobalModule");

                //add settings to the context which can be obtained globally throughout                    the application
                globalContext.addSettings(settings);

                //here we load the sub modules of the global context
                globalContext.loadChildModules(modules);
};

Questo è ciò che abbiamo implementato BoilerPlatejs, un'architettura di riferimento per lo sviluppo del prodotto JavaScript su larga scala.

È possibile utilizzare il pattern Initialize per iniettare qualsiasi valore in un modulo requisito (aka "Iniezione di dipendenza").

Fai una chiamata a richiedere ovunque nel tuo codice:

var MyBackboneModule;

MyBackboneModule = someWayToGetAReferenceToIt();

require("module", function(Module) { 
  Module.initialize(MyBackboneModule);
});

Con il file module.js definito come

define([], function(){
   var BackboneModuleDoingThisAndThat;

   function initialize(pBackboneModule) {
      BackboneModuleDoingThisAndThat = pBackboneModule ;
   };

   function doSomething() {
      var x = BackboneModuleDoingThisAndThat.computeThis(42);
   };


   return { 
      initialize: initialize
   };
});

Puoi definire un singolo globale APP Nel tuo punto di ingresso modulo AMD. APP potrebbe creare e tenere un riferimento ad altri moduli condivisi:

APP = {
    this.settings : function() {
        if(settingsModule == undefined){
            //require, create and return it
        } else {
            return settingsModule;
        }
    }
}

Solo un commento sulla tua risposta: non è necessario definire una funzione nel modulo App_registry:

define({
  global_event_obj: _.extend({}, Backbone.Events);
  models: {}
});

Dovrebbe essere sufficiente.

Vedere: i documenti

Fai attenzione a queste cose però. Ci sono usecasi in cui i moduli di dati condivisi hanno senso. Ma se finisci per usarlo come uno spazio dei nomi globale pseudo, non è molto meglio che usare i globali (non dire che è quello che stai facendo però).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top