我经常从头开始在JS中实现自己的EventDispatcher类。我猜想在浏览器中的某个位置上可以实现DOM元素的实现,但是EventDispatchers甚至对于与DOM完全无关的其他事情也很有用。浏览器中是否可以继承任何标准类?我需要可以调用addEventListener("event", listener)
,removeEventListener("event", listener)
和dispatchEvent("event")
的东西,并且需要它来支持同一事件的多个侦听器。节点中有EventEmitter,但是我对它并不十分熟悉,也不知道它是否可以在浏览器中使用。我是否应该使用它,并可能使用browserify之类的东西来翻译整个东西?
答案 0 :(得分:1)
已经定义了一个接口,可以为您提供所有三种方法,EventTarget
interface EventTarget { void addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options); void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); boolean dispatchEvent(Event event); };
因此您要做的就是从该接口继承
class MyObject extends EventTarget {
myCallback(){
console.log('event triggered');
}
myCallback2(){
console.log('event2 triggered');
}
}
var obj = new MyObject;
obj.addEventListener('test',obj.myCallback);
obj.addEventListener('test',obj.myCallback2);
obj.dispatchEvent(new Event('test'))
答案 1 :(得分:0)
您没有可以扩展的“ no DOM”类,但是RxJS主题可以满足您的需求。
RxJS
您可以
示例:
// Basic example
const emitter = new Subject();
emitter.subscribe(event => console.log(event));
emitter.next({ type: 'my-custom-event', … });
// class example
class MyClass {
change = new Subject();
myFn() {
this.change.next();
}
}
const bar = new MyClass();
bar.change.subscribe(e => console.log('change triggered'));
// test
bar.myFn();
=> logs 'change triggered'
您会发现很多有关angular / typescript的文档,但是rxjs并不依赖于angular。
请参阅:https://rxjs-dev.firebaseapp.com/
EventTarget
只要您在浏览器中,都有EventTarget接口。在大多数浏览器中(因为没有编写Edge,没有IE时),它提供了一个构造函数,您可以对其进行扩展(ECMA 2015)。
class MyClass extends EventTarget {
myFn() {
this.dispatchEvent(new Event('change'));
}
}
const bar = new MyClass();
bar.addEventListener('change', e => console.log('change triggered'));
// just for testing
bar.myFn();
=> logs 'change triggered'
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
答案 2 :(得分:0)
事件分派/侦听是DOM API的一部分,而不是Javascript本身。没有DOM节点,就无法使用此机制。有成千上万个好的,简单的库或更高级的库,并且实现自己很简单(参见microjs上“事件”库的结果量:http://microjs.com/#event)。
您最初的问题是如何使用内置的DOM API事件,因此在下面找到一个仅使用标准DOM API的简单(有点天真)的实现:
// CustomEvent polyfill for IE9-11 from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
(function () {
if ( typeof window.CustomEvent === "function" ) return false;
function CustomEvent ( event, params ) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent( 'CustomEvent' );
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
})();
var events = (function() {
var eventRoot = document.createElement('div');
function event(strOrObj, data) {
return typeof strOrObj === 'string' ? new CustomEvent(strOrObj, data ? {detail: data} : undefined) : strOrObj
};
return {
dispatch: function(evt, data) {
eventRoot.dispatchEvent(event(evt, data));
},
addListener: function(evt, listener1, listener2, etc) {
var listeners = Array.prototype.slice.call(arguments, 1);
listeners.forEach(function(fn) {
eventRoot.addEventListener(evt, fn);
});
},
removeListener: function(evt, listener1, listener2, etc) {
var listeners = Array.prototype.slice.call(arguments, 1);
listeners.forEach(function(fn) {
eventRoot.removeEventListener(evt, listener);
});
}
};
}());
events.addListener('click',
function(e) { console.log(e.detail.data); },
function(e) { console.log(e.type); }
)
events.dispatch('click', {data: 'test'})
对于IE9-11的CustomEvent,您需要一个polyfill(包括在上面)。此解决方案适用于大多数情况,但是开发人员倾向于偏向于非DOMElement事件分发/侦听的发布-订阅模式。您可以在http://microjs.com/#pubsub上找到许多易于使用的库。不要被这些库中的“库”有多“老”所迷惑,它们简单而完整,并且大多数都像魅力一样发挥作用。