Backbone.Radio 用于组件间通信

Backbone.Radio for inter-component communication

假设我在一个页面上有两个组件,用户可以在其中与一个组件交互,而另一个组件应该更新,如下所示:

 component A       |   component B
                   |
 - option 1 link   |   "stuff related to option 1"
 - option 2 link   | 

现在,当我们单击 option 2 link 时,我们希望组件 B 更新。

MarionetteJS 使用(或将在下一个主要版本中使用)Backbone.Radio

我想知道最好的方法。我想到了 2 件事:

1: 在两个组件中使用相同的通道

// Component A
// ...
onOptionClick: function (evt) {
  Backbone.Radio.channel('AvsB').request('update:b', {id: this.model.get('id')});
}

// Component B
// ...
initialize: function () {
  Backbone.Radio.channel('AvsB').reply('update:b', function () {
    // update contents...
  }
}

2:通过使用调解器进一步解耦,例如:组件应该只使用它们的 "own" 通道。

// Component A
// ...
onOptionClick: function (evt) {
  Backbone.Radio.channel('compA').request('option:isUpdated', {id: this.model.get('id')});
}

// Mediator (eg. main.js, a controller, or whatever high-level object)
var channelCompA = Backbone.Radio.channel('compA');
var channelCompB = Backbone.Radio.channel('compB');
channelCompA.reply('option:isUpdated', channelCompB.request('content:shouldUpdate'));

// Component B
// ...
initialize: function () {
  Backbone.Radio.channel('compB').reply('content:shouldUpdate', function () {
    // update contents...
  }
}

选项 2 工作量更大,似乎没有必要。但我真的无法摆脱选项 1 仍然过于具体的感觉。毕竟组件A不应该关心组件B是否存在。

我认为选项 2 不必要地复杂化。

基本上,您是在问事件聚合器模式还是中介器模式更合适。要记住的主要事情是它们 both 紧耦合的解决方案。这在您的示例中是模糊的,因为您在组件之后命名请求("update:b")。这是耦合的来源,而不是您使用相同通道的事实。

更具体地说,如果组件 A 和组件 B 确实不需要相互了解,那么它们的名称不应该是请求名称 API 的一部分。请求应该根据应该完成的实际工作命名(performUpdate,也许?),而不是根据谁在做这项工作。

当然,出于组织或命名空间的目的使用不同的渠道可能仍然有意义。 Mediator 模式肯定有其用途(例如,如果您需要它来拦截请求并以某种方式更改它们)。但是仅仅使用它来盲目地路由请求以试图避免耦合是没有意义的。

您可能会发现 Marionette 的创建者 this article 很有趣,因为它讨论了相同的问题。