我一直在各种环境中使用Dojo,从未找到关于事件与主题的良好解释。我使用这两种机制的理解如下:
在使用Dojo开发自定义小部件时,我曾多次使用的方法是让他们发布到某些主题。其他组件将订阅这些主题并做出适当的反应。但是,这导致难以遵循的代码,因为当您找到订阅特定主题的代码时,您会开始想知道谁将发布到该主题,反之亦然。目前我倾向于让我的自定义小部件提交事件并让控制器监听这些事件并将它们分发给应该对这些事件做出反应的其他小部件。
所以在第一种方法中,主题机制是小部件之间的粘合剂,但是它是分散的,这使得在我的经验中很难长期维护代码。在第二种方法中,控制器类(遵循MVC模式)是粘合剂,它集中了事件处理。
我有兴趣知道这是否正确理解这两种机制。我也会对选择其中一个时应该考虑的任何设计考虑感兴趣(或者甚至混合它们?)。任何关于该主题的精心讨论的指针也将受到赞赏。我一直在关注:http://dojotoolkit.org/documentation/tutorials/1.9/events/但这主要描述了两种机制的工作方式,但对如何构建复杂的应用程序几乎没有任何见解。
答案 0 :(得分:6)
我和你一样对主题和事件有着完全相同的想法。由于JavaScript是事件驱动的,因此它们当然都是事件性的(就像你在第一点所描述的那样)。
事件确实与小部件本身耦合,而主题则不然。我通常会将其视为以下内容:
你是对的,主题让人更难知道原点是什么,但是如果你考虑它,你不需要知道原点。这些主题为您提供了一个API,可以将源与目标分离,从而使您无需了解源。
因为两个小部件都是无关的(这是我之前描述的方法,如前所述),所以在维护代码时通常不需要知道原点是什么。
您需要的是一个编写良好的API,并确保作为目标的源都遵循它。如果API更改(代码维护),您可以使用IDE查找正在发布/订阅的小部件(例如,通过搜索主题名称)并确保每个小部件都已更新。
您还可以选择封装发布/订阅行为,并通过创建如下模块来提供更高级别的API:
define([ "dojo/topic", "dojo/_base/array" ], function(topic, arrayUtils) {
var MY_TOPIC = "/my/topic";
var module = {
observers: [],
notify: function(/** String */ name, /** Integer */ age) {
topic.publish(MY_TOPIC, {
name: name,
age: age
});
},
addObserver: function(/** Function */ callback) {
return this.observers.push(callback) - 1;
},
removeObserver: function(/** Integer */ index) {
this.observers[index] = null;
}
};
topic.subscribe(MYTOPIC, function(data) {
arrayUtils.forEach(module.observers, function(observer) {
if(observer !== null && data.name !== undefined && data.age !== undefined) {
observer(name, age);
}
});
});
return module;
});
使用notify()
函数发布(提供正确的函数参数),并使用其他函数添加/删除观察者。然后,您将使该组件成为唯一的订户,并通知所有观察员。
这样您就不需要了解该主题,并且API是统一的。您只需要确保回调正确使用参数。要维护代码,您只需更改高级API并查找使用此高级组件的模块。这样更容易检测,因为它位于require()
函数中。
当我使用主题时,我通常会创建一个像这样的高级API(根据使用它可能会改变一点)。但我认为所提出的观点很明确,更改主题和修改发送的数据更容易。
答案 1 :(得分:0)
从设计模式和软件架构的角度来看,主题似乎是在道场实施通量的完美机制。找到一篇基本概念为here的文章。