2012-01-12 67 views
13

我目前正在开发一个新的web应用程序。
在不同的amd模块上共享资源

这是我第一次在AMD模块中使用requirejs。

要适应新的范式并不容易 - 据我所知,全局命名空间中没有变量。

在以前的Web应用程序中,我总是在全局命名空间中有一个变量,我可以使用它来在不同模块之间共享多个资源。

现在使用requirejs AMD模块,我使用backbone.js和jquery(都是amd版本 - jquery 1.7.1和backbone.js 0.5.3-optamd3)。

在我的应用程序的某处,我从服务器(用户对象)中获取backbone.js模块。我想从不同的AMD模块访问此模块。我也想有一个应用程序范围的事件对象。

您能否告诉我:requirejs AMD在不同模块间共享资源的正确方法是什么?

回答

31

我找到了解决自己。

谢谢你,IntoTheVoid,为你的答案,但我希望有一个类似AMD的解决方案。这意味着,不再是“污染”全局命名空间。

有2个键我的解决方案:

从阿迪奥斯马尼 “https://github.com/addyosmani/backbone-aura” 和 “https://github.com/amdjs/amdjs-api/wiki/AMD” 的异步模块定义(AMD)API规范。

规范说:“如果工厂是一个函数,它应该只执行一次。”

因此,如果AMD模块多次指定为一个Web应用程序的依赖,依赖不仅没有加载多次,也不执行多次,这是新事物对我来说。它只执行一次,并保持工厂函数的返回值。每个具有相同路径的依赖关系具有相同的对象。这改变了一切。

所以,你只需定义下列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

因此,我可以将模型保存到此全局对象并将其存储到视图和子视图中? – chchrist 2012-04-02 15:52:46

+1

伟大的答案,非常感谢分享 – Alex 2013-06-21 10:41:44

+1

所以这是如何解决这个问题?说第一个模型创建models.abc,secondView如何检索模型,而不用担心模块的加载顺序? – eugene 2013-12-30 08:47:07

0

您可以在入口点AMD模块中定义一个全局的APPAPP可以创建并保持一个参考其他共享的模块:

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

非常感谢您的回答。这个问题是。当我拥有自己的Web应用程序时,只有一个全局变量?可能吗?在AMD范例中是正确的。但是,如果我想创建一个将被其他人使用的框架,那该怎么办?这个人有一个全局变量用于他自己的Web应用程序,另一个通过使用我的框架。 – 2012-01-13 09:04:25

+0

你仍然可以拥有尽可能多的全局变量,这更多的是关于干净代码的问题,不是吗? – 2012-01-13 10:37:15

1

要回答你的问题,即如何公关提供一个应用程序范围的事件对象,你可以创建一个叫做globalContext的amd模块并在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

这个聪明和简单的方法看起来是一个包装字典... – 2013-09-20 16:11:36

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

要小心,这些东西虽然。有共享数据模块有意义的用例。但是,如果最终将其用作伪全局名称空间,那么它不仅仅比使用全局变量更好(不是说这就是你正在做的)。