我想实现一个可以“广播”的自定义事件,而不是发送到特定目标。只有那些已将自己注册为此类事件的侦听器的元素才能接收它们。
我的想法如下。
首先,在代码的各个位置,都会有以下形式的语句:
some_subscriber.on_signal( 'some_signal', some_handler );
我使用的术语signal
是“广播事件”的简写。在上面的表达式中some_subscriber
,通过为其提供处理程序,将自身注册为此类信号的一种(称为“ some_signal”)侦听器。
在代码的其他地方,将有以下形式的语句
publisher.signal_types[ 'some_signal' ].broadcast( event_data );
当执行此类语句时,将生成一个新事件并“广播”。我的意思是,调用该broadcast
方法的代码没有有关发出信号的侦听器的直接信息。
我已经在jsFiddle中实现了这个想法的草图,主要是为了说明我在1以上的词中所描述的内容。(它肯定不是生产级的,而且我不特别相信可以做到这一点。)
此实现的关键元素如下。首先,发布者对象不跟踪其订阅者,如针对此类发布者的工厂方法的实现所示,如下所示:
function make_publisher ( signal_types ) {
// ...
var _
, signal = {}
, ping = function ( type ) {
signal[ type ].broadcast( ... );
}
;
signal_types.forEach( function ( type ) {
signal[ type ] = $.register_signal_type( type );
} );
return { signal_types: signal_types, ping: ping };
}
该发布者对象仅公开两个项目:它广播的信号类型(以表示signal_types
)和一个ping
方法。ping
调用其方法时,发布者通过广播信号进行响应:
signal[ type ].broadcast( ... )
此代码中无处可见此广播的最终接收者。
其次,在代码的其他地方,订户将自己注册为这些广播信号的侦听器,就像这样
$( some_selector ).on_signal( signal_type, some_handler );
注意:基本上不可能使用一个既小又现实的示例来说明此方案的原理。这样做的原因是该方案的优势在于它支持发布者代码和订阅者代码之间非常松散的耦合,而这在一个很小的示例中就从来不需要。相反,在一个小示例中,实现这种松散耦合的代码总是会遇到不必要的复杂情况。因此,重要的是要记住,这种明显的过度复杂性是上下文的产物。松耦合在大型项目中非常有用。特别是,通过发布者/订阅者类型的模式进行的松散耦合是MVC的基本功能之一。
我的问题是:是否有更好的(或至少是更标准的)方式来实现这种“广播”自定义事件的效果?
(我对基于jQuery的答案以及“纯JS”的答案都很感兴趣。)
1这个帖子的一个较早的,命运多almost的版本几乎引起了普遍的不理解,并且(当然)是全盘否定的投票。除了一个例外,我收到的所有评论都对帖子的前提构成了挑战,其中一个直接质疑了我对事件驱动编程基础的理解,等等。我希望通过提出一个至少可以说明我的意思的工作示例它不会像我仅用言语描述时那样让人难以想象。幸运的是,我在较早的帖子中得到的一个有用的评论使我了解了该功能jQuery.Callbacks
。这确实是一个有用的技巧。帖子中提到的草图实现基于jQuery.Callbacks
。
行。
因此,我认为您可以做的是使用本机dispatchEvent
和addEventListener
方法,并将其document
用作发布和订阅这些事件的唯一元素。就像是:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
document.addEventListener('someEvent', doSomething, false);
要制作跨浏览器,您可以:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
if (document.addEventListener) {
document.addEventListener('someEvent', doSomething, false);
} else {
document.attachEvent('someEvent', doSomething);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句