2012-01-12 20 views
13

Actualmente estoy desarrollando una nueva aplicación web.
Compartir recursos en diferentes módulos amd

Esta es la primera vez que uso requirejs con módulos AMD.

No es tan fácil acostumbrarse a ese nuevo paradigma que, como yo lo entiendo, no hay variables en el espacio de nombres global.

En aplicaciones web anteriores siempre tuve una variable en el espacio de nombre global que podía usar para compartir varios recursos en diferentes módulos.

Ahora, con los módulos AMD de requirejs, uso backbone.js y jquery (ambas versiones amd - jquery 1.7.1 y backbone.js 0.5.3-optamd3).

En algún lugar de mi aplicación busco un módulo backbone.js desde el servidor (objeto de usuario). Me gustaría tener acceso a este módulo desde diferentes módulos de AMD. También quiero tener un objeto de evento amplio de la aplicación.

¿Podría decirme: cuál es la forma correcta en que los requisitos de AMD para compartir recursos a través de diferentes módulos?

Respuesta

31

he encontrado una solución a mí mismo.

Gracias, IntoTheVoid, por su respuesta, pero esperaba una solución similar a AMD. Esto significa, no de nuevo, "contaminar" el espacio de nombre global.

hubo 2 llaves de mi solución:

"https://github.com/addyosmani/backbone-aura" de Addy Osmani y "https://github.com/amdjs/amdjs-api/wiki/AMD" la Definición El módulo asincrónico (AMD) especificación de la API.

La especificación dice: "Si la fábrica es una función, solo se debe ejecutar una vez".

lo tanto, si un módulo de AMD se especifica en múltiples ocasiones como una dependencia en una aplicación web, la dependencia no sólo es no se ha cargado varias veces, es también No ejecutado VARIAS VECES, y esto es lo nuevo a mi. Solo se ejecuta una vez y se mantiene el valor de retorno de la función de fábrica. Cada dependencia con la misma ruta tiene el mismo objeto. Y esto cambia todo.

Por lo tanto, sólo tiene que definir el siguiente módulo de AMD:

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

Ahora, en aquellos módulos en los que desee compartir recursos, se declara este módulo app_registry como dependencia y escribir en 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; 
    } 
    ... 

y en el otro:

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. ... 
    } 
    ... 
+1

¿Puedo guardar un modelo en este objeto global y acceder a vistas y subvistas? – chchrist

+1

Excelente respuesta, muchas gracias por compartir – Alex

+1

, ¿cómo soluciona esto el problema? digamos que el primer modelo crea modelos.abc, ¿cómo recupera secondView el modelo sin preocuparse por el orden en que se cargan los módulos? – eugene

0

Puede definir un único APP global en su módulo AMD de punto de entrada. APP podría crear y mantener una referencia a otros módulos compartidos:

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

Muchas gracias por su respuesta. El problema con esto es Cuando tengo mi propia aplicación web, ¿tengo una única variable global? estar en lo cierto en el paradigma de AMD. Pero, ¿qué ocurre si quiero crear un marco que otros usen? Esta persona tiene una variable global para su propia aplicación web y otra usando mi marco. –

+0

Aún puede tener tantas variables globales como quiera, esta es más una pregunta sobre el código limpio, ¿no es así? –

1

para responder a su pregunta de cómo pr Para proporcionar un objeto de evento amplio de la aplicación, puede crear un módulo amd llamado globalContext e instanciarlo en main.js.
A partir de entonces se puede adjuntar a la configuración globalContext y utilizar el contexto global para crear subcomponentes etc.

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

En el archivo global-context.js podemos entonces realizar tareas tales como módulos de carga niño

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); 
}; 

Esto es lo que hemos implementado en BoilerplateJS, una arquitectura de referencia para el desarrollo de productos javascript a gran escala.

+0

Este método inteligente y simple parece ser un diccionario envuelto ... –

1

Puede utilizar el patrón de inicialización para inyectar cualquier valor en un módulo requirejs (también conocido como 'inyección de dependencia').

hacen un llamado requieren cualquier parte del código:

var MyBackboneModule; 

MyBackboneModule = someWayToGetAReferenceToIt(); 

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

Con module.js archivo define como

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

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

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


    return { 
     initialize: initialize 
    }; 
}); 
-1

Sólo un comentario en su propia respuesta - que no es necesario definir una función en su módulo app_registry:

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

Debería ser suficiente.

Ver: the docs

tener cuidado con estas cosas sin embargo. Hay aplicaciones donde los módulos de datos compartidos tienen sentido. Pero si terminas utilizándolo como un espacio de nombres pseudoglobal, no es mucho mejor que solo usar globales (sin decir que eso es lo que estás haciendo).

Cuestiones relacionadas