kjo*_*kjo 9 javascript jquery events broadcast javascript-events
我想实现一个可以"广播"的自定义事件,而不是发送到特定目标.只有那些已将自己注册为此类事件的侦听器的元素才会收到它们.
我的想法如下.
首先,在代码的不同位置,会有表单的陈述
some_subscriber.on_signal( 'some_signal', some_handler );
Run Code Online (Sandbox Code Playgroud)
我正在使用这个术语signal作为"广播事件"的简写.在上面的表达式中some_subscriber,通过为它提供一个处理程序,将自身注册为这种信号的一种类型(称为"some_signal")的监听器.
在代码的其他地方,会有表格的陈述
publisher.signal_types[ 'some_signal' ].broadcast( event_data );
Run Code Online (Sandbox Code Playgroud)
当执行这些语句时,会生成一个新事件并" 广播 ".我的意思是,调用该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 };
}
Run Code Online (Sandbox Code Playgroud)
此发布者对象仅公开两个项目:它广播的信号类型(in signal_types)和ping方法.ping调用其方法时,发布者通过广播信号进行响应:
signal[ type ].broadcast( ... )
Run Code Online (Sandbox Code Playgroud)
此代码中无法看到此广播的最终收件人.
其次,在代码的其他地方,用户将自己注册为这些广播信号的监听器,就像这样
$( some_selector ).on_signal( signal_type, some_handler );
Run Code Online (Sandbox Code Playgroud)
注意:基本上不可能使用既小又实际的例子来说明该方案的基本原理.这样做的原因是该方案的优势在于它支持发布者代码和订阅者代码之间非常松散的耦合,这是一个在小例子中从不必要的功能.相反,在一个小例子中,实现这种松散耦合的代码总是不必要地复杂化.因此,重要的是要记住,这种明显的过度复杂性是上下文的人为因素.松散耦合在大型项目中非常有用.特别是,通过发布者/订阅者类型模式的松散耦合是MVC的基本特征之一.
我的问题是:是否有更好(或至少更标准)的方式来实现"广播"自定义事件的效果?
(我对基于jQuery的答案以及"纯JS"答案感兴趣.)
1这个帖子的早期命运多变的版本几乎普遍不理解,而且(当然)是非常典型的向下投票.除了一个例外,我所提出的所有评论都对帖子的前提提出了挑战,并且直接质疑我对事件驱动编程基础知识的掌握等等.我希望通过提出一个至少我的意思的工作示例它不会像我单独用文字描述的那样完全不可思议.幸运的是,我在早期帖子中得到的一个有用的评论告诉了我这个功能jQuery.Callbacks.这确实是一个有用的提示; 帖子中提到的草图实现基于jQuery.Callbacks.
Tah*_*med 15
行.
因此,我认为您可以使用本机dispatchEvent和addEventListener方法,并将其document用作发布和订阅这些事件的唯一元素.就像是:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
document.addEventListener('someEvent', doSomething, false);
Run Code Online (Sandbox Code Playgroud)
要制作跨浏览器,您可以:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
if (document.addEventListener) {
document.addEventListener('someEvent', doSomething, false);
} else {
document.attachEvent('someEvent', doSomething);
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处和此处阅读有关此主题的更多信息.希望这可以帮助.