骨干.用于组件间通信的无线电



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

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

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

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

我想知道做这件事的最好方法是什么。我想到了两件事:

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:通过使用中介进一步解耦,例如:组件应该只使用它们"自己的"通道。

// 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太复杂了。

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

更具体地说,如果组件A和组件B真的不需要知道对方,那么它们的名字就不应该作为请求名的API的一部分。请求应该以实际要做的工作命名(也许是performUpdate ?),而不是以谁在做这项工作命名。

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

您可能会觉得木偶创作者的这篇文章很有趣,因为它讨论了同样的问题。

最新更新