我目前正在开发一个新的网络应用程序。
这是我第一次使用带有AMD模块的requirejs。
习惯那种新的范例并不容易 - 据我所知 - 全局命名空间中没有变量。
在以前的Web应用程序中,我总是在全局命名空间中有一个变量,我可以使用它来跨不同模块共享多个资源。
现在使用requirejs AMD模块,我使用backbone.js和jquery(两个amd版本 - jquery 1.7.1和backbone.js 0.5.3-optamd3)。
在我的应用程序的某处,我从服务器(用户对象)获取backbone.js模块。我想从不同的AMD模块访问该模块。我还想要一个应用程序范围的事件对象。
你能否告诉我:requirejs AMD在不同模块之间共享资源的正确方法是什么?
答案 0 :(得分:31)
我自己找到了解决方案。
谢谢你,IntoTheVoid,你的答案,但我希望有类似AMD的解决方案。这意味着,不再是,"污染"全局命名空间。
我的解决方案有两个关键:
" https://github.com/addyosmani/backbone-aura"来自Addy Osmani和" https://github.com/amdjs/amdjs-api/wiki/AMD"异步模块定义(AMD)API规范。
规范说:"如果工厂是一个功能,它应该只执行一次。"
因此,如果在Web应用程序中多次指定amd模块作为依赖项,则依赖项不仅 NOT LOADED MULTIPLE TIMES ,它还 NOT EXECUTED MULTIPLE TIMES 强>,这对我来说是新事物。它只执行一次,并保留工厂功能的返回值。具有相同路径的每个依赖项具有相同的对象。这会改变一切。
因此,您只需定义以下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 :(得分:1)
要回答关于如何提供应用程序范围事件对象的问题,可以创建一个名为globalContext的amd模块并在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产品开发的参考架构。
答案 2 :(得分:1)
您可以使用初始化模式将任何值注入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
};
});
答案 3 :(得分:0)
您可以在入口点AMD模块中定义单个全局APP
。 APP
可以创建并保留对其他共享模块的引用:
APP = {
this.settings : function() {
if(settingsModule == undefined){
//require, create and return it
} else {
return settingsModule;
}
}
}
答案 4 :(得分:-1)
只是评论你自己的答案 - 你不需要在你的app_registry模块中定义一个函数:
define({
global_event_obj: _.extend({}, Backbone.Events);
models: {}
});
应该足够了。
请参阅:the docs
但要小心这些事情。共享数据模块有用的用例。但是如果你最终将它用作伪全局命名空间,那么它只比使用全局变量更好(不是说你正在做的事情)。