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

时间:2013-06-01 15:24:22

标签: backbone.js event-handling

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

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

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

1 个答案:

答案 0 :(得分:13)

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

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

当你有:

时,我发现中央事件总线非常有用
  1. 单个事件发布实例和众多事件接收器。
  2. 许多事件发布实例和单个事件接收器
  3. 当事件接收器实例或发布者实例是动态的,因此在应用程序的生命周期中创建和销毁时,上述情况下中央事件总线的好处变得更加明显。例如,请考虑以下单页应用:

    1. 单页应用必须拉伸以适合浏览器窗口宽度。
    2. 单页应用程序主要是一组选项卡式视图,但选项卡的数量是动态的,因为它们是由用户创建和销毁的
    3. 选项卡的内容都是不同的,除了它们有一个主要的内容区域,在考虑其他兄弟元素的宽度后必须拉伸以适应可用的宽度
    4. 由于标签内容不断变化,需要在许多不同的点进行调整大小。
    5. 在上述情况下,无论具体情况如何,中央总线模型都能很好地工作。代码示例如下:

      申请级别

      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);
              });
          }
      }
      

      在您的观看中

      每当需要调整某件事物的大小时,您就会触发该事件,例如:

      App.Events.trigger("fitRemainingWidth:app", this.$(".main-content"), this);
      

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

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

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

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

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

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

      最后,关于事件的可追溯性,您始终可以为事件总线中的OnOff函数编写一个包装器,它们都调用普通On和{{ 1}}函数,但也向寄存器添加/删除信息,包含哪些对象绑定到哪些事件。您可以使用它来调试并写入有关这些对象的控制台信息,这样您就可以在任何时间清楚地了解事件总线及其侦听器的状态。我从来没有想过这样做,但没有理由你不能;)

      发布编辑 :tsiki关于使用本地活动总线的评论很好。在上面的示例中,我使用了许多选项卡式邮箱,您可以为每个用户邮箱选项卡视图使用本地事件总线。如果每个邮箱选项卡视图本身都非常复杂,包含许多嵌套的子视图和要生成/处理的大量事件,您可能希望这样做。