2012-01-12 3 views
13

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

Это первый раз, когда я использую requirejs с модулями AMD.

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

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

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

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

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

ответ

31

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

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

Были 2 ключа к моему решению:

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

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

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

Таким образом, вы просто определить следующие драмы модуля:

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

Итак, я могу сохранить модель для этого глобального объекта и получить доступ к ней в виде представлений и подзаголовков? – chchrist

+1

Отличный ответ, спасибо большое за обмен – Alex

+1

, так как это решает проблему? скажем, первая модель создает models.abc, как secondView извлекает модель, не беспокоясь о порядке загрузки модулей? – eugene

0

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

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

Большое спасибо за ваш ответ. Проблема с этим. Когда у меня просто есть собственное веб-приложение, возможно, иметь одну глобальную переменную? быть правым в парадигме AMD. Но что, если я хочу создать структуру, которая будет использоваться другими. У этого человека есть одна глобальная переменная для его собственного веб-приложения, а другая - с помощью моей инфраструктуры. –

+0

У вас все еще есть столько глобальных переменных, которые вам нравятся, это вопрос о чистом коде, не так ли? –

1

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

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

В глобальном 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

Этот умный и простой метод выглядит как завернутый словарь ... –

1

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

сделать требуют вызова в любом месте вашего кода:

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

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

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

Должно быть достаточно.

См: the docs

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