3

我正在构建一个 Backbone 应用程序,使用 require.js 进行模块化加载,并使用 Marionette 来帮助我的应用程序结构和功能。我已经为事件聚合器设置了一个 require 模块,如下所示:-

define(['backbone', 'marionette'],function(Backbone, Marionette){
    var ea = new Backbone.Wreqr.EventAggregator();
    ea.on('all', function (e) { console.log("[EventAggregator] event: "+e);});
    return ea;
});

我希望将它传递到我的其他 require 模块中,并让它充当中央事件处理和消息传递组件,我在这方面取得了一些成功。我可以将通风口作为依赖项传递给其他模块,而不会出现这样的问题:-

define(['marionette', 'text!templates/nav.html', 'shell/vent'], function (Marionette, text, vent) {
    return SplashView = Marionette.ItemView.extend({
        template : text,
        events : {
            'click #splashContinueButton': 'onButtonClick'
        },
        onButtonClick : function(evt) {
            vent.trigger('onSplashContinueClick'); 
        }
    });
});

我遇到的问题是,尽管所有事件都在我的应用程序的不同位置触发(我可以在控制台日志中看到),但我无法在我的应用程序的某些部分收听它们。例如,我有一个 Marionette 模块(在运行时作为 require 模块加载),它试图获取一些这样的事件:-

var SplashModule = shellApp.module("SplashModule");
SplashModule.addInitializer(function(){
    vent.on("onSplashModelLoaded", this.onSplashModelLoaded);
    vent.on("onSplashContinueClick", this.onSplashContinueClick);
}

我什么也没得到,即使我从这个地方记录通风口,我也可以将它视为一个对象。在日志中,它包含一个事件数组,实际上只包含根级应用程序正在侦听的事件,而不是应用程序其他部分正在侦听的任何其他事件。这就是我的理解分崩离析的地方:我认为我可以将事件聚合器用作跨应用程序结构的全局通信和消息传递系统。任何人都可以对可能发生的事情有所了解吗?

非常感谢,

山姆

*更新/编辑/解决方案*

您好,好吧,我现在可以正常工作了(发布上述内容后仅 5 分钟-doh!)。基本上,在模块的初始化事件中添加我的监听器为时过早(据我所知)。我将它们沿着功能链进一步移动,现在一切都按预期运行。

4

2 回答 2

4

为了让它正常工作,我必须做出的改变是我必须在模块中进一步删除通风口监听器“onSplashContinueClick”。在此更改之前,它位于初始化函数中,但现在它更进一步:-

define(["backbone", "marionette", "shell/vent", "shell/shellapp", "shell/splash/splashmodel", "shell/splash/splashview"], function(Backbone, Marionette, vent, shellApp, SplashModel, SplashView){

var SplashModule = shellApp.module("SplashModule");

SplashModule.addInitializer(function(){
    trace("SplashModule.addInitializer()");
    SplashModule.model = SplashModel;
    SplashModule.model.fetch({
        success:function(){
            //trace("splashModel.fetch success")
            SplashModule.onSplashModelLoaded();
        },
        error:function() {
            //trace("splashModel.fetch error")
        }
    });

});
SplashModule.addFinalizer(function(){

});
SplashModule.initView = function () {
    //trace("SplashModule.initView()");
    SplashModule.mainView = new SplashView({model: SplashModel});
    shellApp.mainRegion.show(SplashModule.mainView);
    vent.on("onSplashContinueClick", this.onSplashContinueClick);

};
SplashModule.end = function () {
    trace("SplashModule.end()");
    shellApp.mainRegion.close();
    vent.trigger("onSplashModuleComplete");
};


// events
SplashModule.onSplashModelLoaded = function () {
    trace("SplashModule.onSplashModelLoaded");
    SplashModule.initView();
};
SplashModule.onSplashContinueClick = function () {
    trace("SplashModule.onSplashContinueClick()");
    SplashModule.end();
};


return SplashModule;
});

我猜这个问题与依赖项何时可用和/或准备就绪的顺序有关。我相信在初始化方法期间,通风口还没有为侦听器准备好。这很可能与我Marionette在 require 模块中对模块的使用有关。

于 2013-04-23T14:38:16.170 回答
1

使用RequireJS还涉及一些干净的模块... Backbone.Wreqr.EventAggregatorMarionette.js的一部分的模块(为了记录,Derrick Bailey 只是将这个由其他人制作的模块放入他的库中,Backbone也是如此.BabySitter ) 使用 RequireJS,您只能看到库导出的内容,在这种情况下 Marionette 我认为最好的方法是将 marionette 拆分为 3 个模块,它实际上包含backbone.babysitter、backbone.wreqr 和 marionette。然后你必须为每个模块创建一个 shim

我用这个

require.config({    
    baseUrl: "/Scripts/",        
    paths: {
     "json2": "vendor/JSON2",
     "backbone": "vendor/backbone/backbone.1.1.0",
     "localStorage": "vendor/backbone/backbone.localStorage.1.1.9",
     "marionette": "vendor/backbone/backbone.marionette.1.8.6",
     "bootstrap": "vendor/bootstrap/bootstrap.3.1.1",
     "jquery": "vendor/jquery/jquery.1.8.3",
     "text": "vendor/Require/text.0.27.0",
     "underscore": "vendor/underscore/underscore.1.5.2",
     "wreqr": "vendor/backbone/backbone.wreqr",
     "babysitter": "vendor/backbone/backbone.babysitter",
  },
  shim: {
     "json2": {
         exports: "JSON"
     },
     "jquery": {
        exports: "$"
     },
     "underscore": {
        exports: "_"
     },
     "bootstrap": {
        deps: ["jquery"]
     },
    "backbone": {
        deps: ["underscore", "jquery"],
        exports: "Backbone"
     },
     "validation": {
        deps: ["backbone"],
        exports: "Backbone.Validation"
     },
     "wreqr": {
        deps: ["backbone", "underscore"],
        exports: "Backbone.Wreqr"
     },
     "marionette": {
        deps: ["backbone", "babysitter", "wreqr"],
        exports: "Backbone.Marionette"
     },
     "localStorage": {
        deps: ["backbone"],
        exports: "Backbone.LocalStorage"
     }
 }
});

一旦你有了这个,你就可以使用 wreqr 你的脚本中有另一个技巧,你写的事实 define(['backbone', 'marionette'],function(Backbone, Marionette){ 有点令人不安,因为你永远不会知道在你的实现中使用 Backbone 或 Marionette 是否是故意的。我的意思是,与骨干和木偶相关的命名空间是骨干和木偶;我建议您将 Backbone 别名为骨干,将 Marionette 别名为 Marionette,如下所示: define(['backbone', 'marionette'],function(backbone, marionette){. 这样做,您将能够检查您的模块是否已被 RequireJS 按需下载。

然后一旦创建了垫片,你的第一个块代码应该是这样的

define(["wreqr"],function(wreqr){
    var ea = new wreqr.EventAggregator();
    ea.on('all', function (e) { console.log("[EventAggregator] event: "+e);});
    return ea;
});
于 2015-02-26T15:23:46.423 回答