我应该使用带有backbone.js的中央事件总线吗?

los*_*ost 8 event-handling backbone.js

我目前正在开发我的第一个backbone.js应用程序.事件的概念对我来说非常熟悉,但如果我应该使用中央事件调度员,我有疑问.一般来说,我看到这两种方法:

  • 直接将事件发布者和事件接收者连接在一起.(我从这种方法开始.)
  • 使用事件总线并将发布者和接收者连接到此总线.

在应用程序的长时间可维护性和事件的可追溯性方面,使用事件总线是否有利?

dca*_*son 13

是否使用中央事件总线或直接将事件连接在一起应根据具体情况进行评估.根据具体情况,有时你会偏爱另一个.

我会尽可能使用中央事件总线,因为发布者和接收者没有紧密耦合.在我看来,这使您的代码更易于维护和灵活.

我发现中央事件总线非常有用:

  1. 单个事件发布实例和众多事件接收器.
  2. 许多事件发布实例和单个事件接收器

当事件接收器实例或发布者实例是动态的并且因此在应用程序的生命周期中被创建和销毁时,在上述情况下中央事件总线的益处变得更加明显.例如,请考虑以下单页应用:

  1. 单页应用程序必须拉伸以适合浏览器窗口宽度.
  2. 单页面应用程序主要是一组选项卡式视图,但是选项卡的数量是动态的,因为它们是由用户创建和销毁的
  3. 选项卡的内容都是不同的,除了它们有一个主要的内容区域,在考虑其他兄弟元素的宽度后必须拉伸以适应可用的宽度
  4. 由于标签的内容不断变化,调整大小需要在许多不同的点发生.

在上述情况下,无论具体情况如何,中央总线模型都能很好地工作.代码示例如下:

应用水平

var App = {

    init: function () {
        // Event to resize width of element to remaining width
        App.Events.on("fitRemainingWidth:app", this.fitRemainingWidth);
     },

    // event pub sub for the app.
    Events: _.extend({}, Backbone.Events),

    // function that expands an element, or elements to the remaining width in the window. 
    fitRemainingWidth: function(targetEls) {
        var els = $(targetEls);
        _.each(els, function (e) {
            var el = $(e);
            var cont = el.parent();
            newWidth = cont.innerWidth();
            otherElements = cont.children().not(el);
            otherElementsWidth = 0;

            otherElements.each(function () {
                otherElementsWidth += $(this).outerWidth();
            });

            el.width(newWidth - otherElementsWidth);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的意见

每当需要调整某些内容时,都会触发该事件,例如:

App.Events.trigger("fitRemainingWidth:app", this.$(".main-content"), this);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这非常有用,因为fitRemainingWidth函数可以应用于任何内容,并且您永远不知道将来可能要使用哪些视图或何时需要调用它.

所以当我发现不使用中央事件总线时,我想我应该继续前进.我确信还有其他情况,但对我来说主要的是接收器需要连接到发布者的特定实例.例如,如果我们继续使用选项卡式应用程序示例,可以说每个选项卡的内容是特定人员邮箱的拆分视图.在每个拆分视图中都有一个列表窗格,其中显示了一组电子邮件和一个阅读窗格,其中显示了列表中当前所选邮件的内容.

在这种情况下,我们希望在单击电子邮件时触发"选中:电子邮件"事件,并将相应的阅读窗格绑定到该事件,以便显示电子邮件的内容.

假设我们打开了十个邮箱标签,每个标签都有自己的电子邮件列表窗格和阅读窗格.这使得十个电子邮件列表和十个阅读窗格.如果我在这个场景中使用中央事件总线,当我从其中一个列表中触发"选中:电子邮件"时,从事件总线接收这些事件的阅读窗格需要有自己的智能来尝试和工作所选的电子邮件是否是他们需要显示的内容.每个阅读窗格尝试解决这个问题并不是很理想,并且涉及到不必要的逻辑.对于阅读窗格而言,只需接收带有电子邮件对象的"已选择:电子邮件"事件作为其有效负载并且只显示它就会好得多.

因此,在这种情况下,最好使每个邮箱选项卡视图负责连接其特定子视图实例及其模型和集合的事件.在我们的示例中,这意味着电子邮件列表视图的特定实例及其集合和阅读窗格视图的特定关联实例.

总而言之,我建议每个用例都有用例,并且您应该尽量明智地为每个遇到的情况选择正确的方法.使用两者并学习在哪种情况下适合.

最后,关于事件的可追溯性,可以随时写了一个包装OnOff功能在你的事件总线,这两个调用正常OnOff功能,而且还添加/删除信息包含哪些对象绑定到该事件寄存器.您可以使用它来调试并写入有关这些对象的控制台信息,这样您就可以在任何时间清楚地了解事件总线及其侦听器的状态.我从来没有想过这样做,但没有理由你不能;)

帖子编辑:tsiki关于使用本地事件总线的评论很好.在上面的示例中,我使用了许多选项卡式邮箱,您可以为每个用户邮箱选项卡视图使用本地事件总线.如果每个邮箱选项卡视图本身都非常复杂,包含许多嵌套子视图和要生成/处理的大量事件,则可能需要执行此操作.