Обмен ресурсами между различными модулями AMD - PullRequest
13 голосов
/ 13 января 2012

Сейчас я занимаюсь разработкой нового веб-приложения.

Впервые я использую requirejs с модулями AMD.

Это не так простопривыкнуть к этой новой парадигме: в глобальном пространстве имен, как я понимаю, нет переменных.

В предыдущих веб-приложениях у меня всегда была одна переменная в глобальном пространстве имен, которую я мог использовать для обменанесколько ресурсов в разных модулях.

Теперь, используя модули AMD requirejs, я использую backbone.js и jquery (обе версии amd - jquery 1.7.1 и backbone.js 0.5.3-optamd3).

Где-то в моем приложении я получаю модуль backbone.js с сервера (пользовательский объект).Я хотел бы иметь доступ к этому модулю из разных модулей AMD.Я также хочу иметь объект события всего приложения.

Не могли бы вы сказать мне: как правильно использовать requirejs AMD для совместного использования ресурсов между различными модулями?

Ответы [ 5 ]

31 голосов
/ 15 января 2012

Я сам нашел решение.

Спасибо, IntoTheVoid, за ваш ответ, но я надеялся на AMD-подобное решение.Это означает, что снова «загрязняет» глобальное пространство имен.

В моем решении было 2 ключа:

"https://github.com/addyosmani/backbone-aura" от Addy Osmani и" https://github.com/amdjs/amdjs-api/wiki/AMD" спецификация API определения асинхронного модуля (AMD).

Спецификация гласит: «Если фабрика является функцией, она должна выполняться только один раз».

Итак, если модуль amdуказанная несколько раз в качестве зависимости в веб-приложении, эта зависимость не только НЕ ЗАГРУЖАЕТСЯ НЕСКОЛЬКО РАЗ , она также НЕ ВЫПОЛНЕНА НЕСКОЛЬКО РАЗ , и это для меня новость.Он выполняется только один раз, и возвращаемое значение заводской функции сохраняется.Каждая зависимость с одинаковым путем имеет один и тот же объект.И это все меняет.

Итак, вы просто определяете следующий модуль amd:

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

Теперь в тех модулях, где вы хотите поделиться ресурсами, вы объявляете этот модуль app_registry как зависимость ипишите в одном:

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

, а в другом:

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 голос
/ 31 августа 2012

Вы можете использовать шаблон инициализации для вставки любого значения в модуль requirejs (он же «внедрение зависимостей»).

Выполните вызов require в любом месте вашего кода:

var MyBackboneModule;

MyBackboneModule = someWayToGetAReferenceToIt();

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

СФайл module.js определен как

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

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

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


   return { 
      initialize: initialize
   };
});
1 голос
/ 28 августа 2012

Чтобы ответить на ваш вопрос о том, как предоставить объект события всего приложения, вы можете создать модуль amd с именем globalContext и создать его экземпляр в файле main.js.
После этого вы можете присоединить настройки к globalContext и использовать глобальныйконтекст для создания подкомпонентов и т. д.

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

В файле global-context.js мы можем затем выполнять такие задачи, как загрузка дочерних модулей

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

Это то, что мы реализовали в BoilerplateJS , эталонная архитектура для разработки крупномасштабных продуктов на JavaScript.

0 голосов
/ 07 ноября 2013

Просто комментарий к вашему собственному ответу - вам не нужно определять функцию в вашем модуле app_registry:

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

должно хватить.

См .: Документы

Будьте осторожны с этими вещами, хотя. Есть случаи, когда модули с общими данными имеют смысл. Но если вы в конечном итоге используете его в качестве псевдоглобального пространства имен, это не намного лучше, чем просто использование глобальных переменных (не говоря уже о том, что вы делаете).

0 голосов
/ 13 января 2012

Вы можете определить один глобальный APP в модуле AMD вашей точки входа. APP может создавать и хранить ссылку на другие общие модули:

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