【问题标题】:How to work with events in pure JavaScript?如何在纯 JavaScript 中处理事件?
【发布时间】:2014-07-25 23:38:30
【问题描述】:

这可能是重复的,但是,在 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]' is not a constructor (evaluating 'new Event("end")')”。

这意味着不会工作?有没有办法在纯 JavaScript 中创建和调度自定义事件(不使用 jQuery 或类似的东西)?

【问题讨论】:

  • 如果 new EventSafari 中抛出错误,请检查您是否拥有最新版本的浏览器,如果是,您可能需要向 Apple 提交错误报告. new Event 适用于所有主要浏览器; Chrome、FireFox 和 IE9+

标签: javascript events custom-events


【解决方案1】:

我之前有this same question

这是我想出的解决方案

需要 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"));

酷!


现在让我们看看它如何与您的代码一起工作。 Here's a demo.

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

最后,这是一个与 ecmascript < 5 兼容的 Emitter 版本

// 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 了解旧版浏览器中的触发事件

你可以做一个这样的 polyfill(未经测试)

if (typeof Event !== "function") {
  function Event(type) {
    var e = document.createEvent("Event");
    e.initEvent(type, true, true);
    return e;
  }
}

【讨论】:

  • 我同意!看起来很有趣,我不完全理解,但做了测试。错误是一样的,只是指向现在“新事件”在哪里。
  • 在 FireFox 中有效!我对我的示例进行了改编,并最终发送了“结束”事件。所以它接缝它还没有那么受欢迎......
  • @GustavoPinent,我提供了与您的代码更匹配的答案的改编。也请查看the fiddle demo
  • 谢谢。我会留下这个问题,看看是否有人知道如何让它在旧的 ecmascript 版本中工作。
  • @GustavoPinent,我刚刚为旧版浏览器添加了一个版本 :) 最大的不同是你不能依赖 Function.prototype.bindArray.prototype.forEach
【解决方案2】:

在这里为我自己的教会传道,但我最近刚好在这方面工作,并编写了一个处理事件和继承的小型 javascript。

如果您想查看一些示例,这一切都在 github 上:

http://nicolasbize.com/moojs

(包含可点击的链接)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 2011-07-24
相关资源
最近更新 更多