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 很有趣,因为它讨论了相同的问题。
假设我在一个页面上有两个组件,用户可以在其中与一个组件交互,而另一个组件应该更新,如下所示:
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 很有趣,因为它讨论了相同的问题。