стандартный класс EventDispatcher браузера для наследования

1

Я часто реализую свой собственный класс EventDispatcher в JS с нуля. Я предполагаю, что есть некоторая реализация его где-то в браузерах для элементов DOM, но EventDispatchers полезны даже для других вещей, не связанных вообще с DOM. Есть ли какой-либо стандартный класс в браузерах, который я могу унаследовать? Мне нужно что-то, где я могу вызвать addEventListener("event", listener), removeEventListener("event", listener) и dispatchEvent("event") и мне нужно, чтобы он поддерживал несколько прослушивателей для одного и того же события. Есть EventEmitter из узла, но я не очень хорошо знаком с ним, и я не знаю, будет ли он работать в браузере. Должен ли я использовать его и, возможно, перекрыть всю вещь с помощью чего-то вроде браузера?

  • 0
    Есть EventTarget, который является интерфейсом, откуда вы получаете методы add / removeEventListener и dispatch, это то, что вы ищете?
  • 0
    EventTarget работает. Это именно то, что я искал.
Теги:

3 ответа

1
Лучший ответ

Существует уже определенный интерфейс, который дает вам все 3 метода, 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'))
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'})

Для CustomEvent для IE9-11 вам понадобится полиполк (см. Выше). Это решение будет работать в большинстве случаев, но разработчики предпочитают шаблоны публикации-подписки для диспетчеризации/прослушивания не-DOMElement. Вы найдете много простых в использовании библиотек на http://microjs.com/#pubsub. Не обманывайтесь, как "старые" некоторые из этих библиотек, они просты и полны, и большинство работает как шарм.

  • 0
    Для этого вам не нужен элемент DOM, просто нужен объект, который реализует или наследует от EventTarget
  • 0
    Мой первоначальный вопрос был о том, как вообще не использовать DOM. EventTarget - это то, что я искал.
Показать ещё 2 комментария
0

Нет класса "без DOM", который вы могли бы расширить, но субъекты RxJS могут соответствовать вашим потребностям.

RxJS

Вы можете

  • подписывайте столько слушателей, сколько вам нужно.
  • call next(), чтобы "запустить" событие

Пример:

// 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'

Вы найдете много документации вокруг углового/машинописного текста, но rxjs не зависит от углового.

См. 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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню