Как работать с событиями на чистом JavaScript?

Возможно, это дублируется, однако с появлением новых браузеров в мире JavaScript все быстро меняется. Я использую некоторые ресурсы, которые использовались в AS3 давным-давно, и теперь они, наконец, популярны в JavaScript. Однако я все еще не могу заставить события работать в моих классах. Я сделал этот простой пример, используя Mozilla MDN в качестве руководства:

var endEvent = new Event("end");

function MyClass(text){
    this.text = text;
    this.show = function(){
        console.log("MyText: "+this.text);
        this.dispatchEvent(endEvent);
    }
}

function End(evt){
    console.log("Event dispatched: "+evt);
}

function run(){
    var MyInstance = new MyClass("I have something to say...");
    MyInstance.addEventListener("end", End, false);
    MyInstance.show();
}

В первой строке Safari возвращает: «TypeError: '[object EventConstructor]' не является конструктором (оценка 'new Event ("конец")')».

значит не получится? Есть ли способ создавать и отправлять пользовательские события в PURE JavaScript (не будет использовать jQuery или что-то подобное)?


person Gustavo    schedule 25.07.2014    source источник
comment
Если new Event выдает ошибку в Safari, убедитесь, что у вас установлена ​​новейшая версия браузера, и если это так, вы можете отправить отчет об ошибке в Apple. new Event будет работать во всех основных браузерах; Chrome, FireFox и IE9+   -  person Paul S.    schedule 26.07.2014


Ответы (2)


У меня был этот же вопрос немного назад

Вот решение, которое я придумал

требуется ecmascript >= 5


function Emitter() {
  var eventTarget = document.createDocumentFragment();

  function delegate (method) {
    this[method] = eventTarget[method].bind(eventTarget);
  }

  [
    "addEventListener",
    "dispatchEvent",
    "removeEventListener"
  ].forEach(delegate, this);
}

Теперь "класс", который его использует

function Example() {
  Emitter.call(this);
}

Давайте попробуем прямо сейчас!

var e = new Example();

e.addEventListener("something", function(event) {
  alert("something happened! check the console too!");
  console.log(event);
});

e.dispatchEvent(new Event("something"));

Прохладно!


Теперь посмотрим, как он работает с вашим кодом. Вот демонстрация.

// include function Emitter from above

function MyClass(text){

  Emitter.call(this);

  function show() {
    console.log("MyText:", text);
    this.dispatchEvent(new Event("end"));
  }

  this.show = show;
}

function onEnd(event){
  console.log("Event dispatched:", event);
}

function run(){
  var myInstance = new MyClass("I have something to say...");
  myInstance.addEventListener("end", onEnd, false);
  myInstance.show();
}

run();

Выход

MyText: I have something to say... 
Event dispatched: Event {
  bubbles: false
  cancelBubble: false
  cancelable: false
  clipboardData: undefined
  currentTarget: null
  defaultPrevented: false
  eventPhase: 0
  path: NodeList[0]
  returnValue: true
  srcElement: null
  target: null
  timeStamp: 1406332794168
  type: "end"
  __proto__: Event
}

Наконец, вот версия Emitter, совместимая с ecmascript < 5

// IE < 9 compatible
function Emitter() {
  var eventTarget = document.createDocumentFragment();

  function addEventListener(type, listener, useCapture, wantsUntrusted) {
    return eventTarget.addEventListener(type, listener, useCapture, wantsUntrusted);
  }

  function dispatchEvent(event) {
    return eventTarget.dispatchEvent(event);
  }

  function removeEventListener(type, listener, useCapture) {
    return eventTarget.removeEventListener(type, listener, useCapture);
  }

  this.addEventListener = addEventListener;
  this.dispatchEvent = dispatchEvent;
  this.removeEventListener = removeEventListener;
}

См. document.createEvent для запуска событий в устаревших браузерах.

Вы можете сделать такой полифилл (непроверенный)

if (typeof Event !== "function") {
  function Event(type) {
    var e = document.createEvent("Event");
    e.initEvent(type, true, true);
    return e;
  }
}
person Mulan    schedule 25.07.2014
comment
Я согласен! Сем интересно, я не совсем понял, но сделал тест. Ошибка та же, просто указывает, где теперь находится новое событие. - person Gustavo; 26.07.2014
comment
В FireFox работает! Я сделал адаптацию к своему примеру, и он, наконец, отправил конечное событие. Так что, похоже, он еще не так популярен... - person Gustavo; 26.07.2014
comment
@GustavoPinent, я предоставил адаптацию своего ответа, которая больше соответствует вашему коду. См. также демонстрацию скрипта. - person Mulan; 26.07.2014
comment
Спасибо. Я оставлю вопрос живым, чтобы узнать, знает ли кто-нибудь, как заставить его работать в более старых версиях ecmascript. - person Gustavo; 26.07.2014
comment
@GustavoPinent, я только что добавил версию для старых браузеров :) Самое большое отличие в том, что вы не можете зависеть от Function.prototype.bind или Array.prototype.forEach. - person Mulan; 26.07.2014
comment
Круто, но есть еще новая проблема Event. Похоже, это недавняя спецификация DOM, поэтому она не будет работать со старыми браузерами. Взгляните на работы karlipoppins. - person Gustavo; 26.07.2014
comment
@GustavoPinent, я просмотрел работу karlipoppins и даже не могу начать ее комментировать. Это заходит так далеко против сути того, как я решаю проблемы. Во всяком случае, проблема, о которой вы говорите, решается многими полифилл-библиотеками. Оформить заказ modernizr в качестве примера. Я также обновил свой ответ, чтобы показать возможное решение для этого. - person Mulan; 27.07.2014
comment
@GustavoPinent, дело в том, что, конечно, есть масса факторов, о которых следует беспокоиться, если вы хотите поддерживать версии браузера более 15 лет. Самостоятельное решение этих проблем для каждого фрагмента кода, который вы пишете, — это не то, с чем вам нужно иметь дело. Ознакомьтесь с некоторыми библиотеками полифиллов, чтобы упростить разработку устаревшей поддержки. - person Mulan; 27.07.2014
comment
Я тебя люблю! Это работает! Возможно, вы меня неправильно поняли, я тестирую Safari 5.1 (2013) и IE 9 как самые старые браузеры, поддерживаемые моим кодом, и я делаю свою собственную библиотеку, чтобы создать стандарт для своих клиентов. Этот код для Event — это просто решения, которые я собираю в один пакет (может быть, я неправильно понял работу kerlipoppins). modernizr может быть слишком много, но я буду держать под рукой. Спасибо еще раз! - person Gustavo; 28.07.2014

Я проповедую здесь для своей собственной церкви, но я работал над этим совсем недавно и написал крошечный javascript, который обрабатывает события и наследование.

Все это есть на github, если вы хотите посмотреть несколько примеров:

http://nicolasbize.com/moojs

(содержит кликабельные ссылки)

person koni    schedule 26.07.2014
comment
Я работаю именно так. Я мог бы использовать это решение, если вы не возражаете. Я не в первый раз пытаюсь здесь: stackoverflow.com/questions/22571250/. Надеюсь на успех в этот раз! - person Gustavo; 26.07.2014