触发和捕获自定义事件

And*_*dez 13 javascript dom-events

想象一下这个场景(它只是一个场景):

  • 我有一个全局计数器,每次鼠标点击都会增加.
  • 当我达到50次点击时,我想发起一个名为"reachCount"的自定义事件
  • 我想注册我的窗口对象以捕获该事件
    window.addEventListener('reachedCount', function(args){alert(args.count);}, false)

所以,我的问题是我不知道,并且无法在任何地方找到我如何将参数传递给我的eventHandler.此外,我曾尝试过Rikudo发布的方法,但它在IE lt 9中不起作用.

这可能吗?怎么样?

HBP*_*HBP 16

使用Rikudo Sennin的答案,您可以通过将参数放入事件本身来将参数传递给事件处理程序,就像DOM处理程序一样!

function fireEvent(name, target, param1, param2) {
    //Ready: create a generic event
    var evt = document.createEvent("Events")
    //Aim: initialize it to be the event we want
    evt.initEvent(name, true, true); //true for can bubble, true for cancelable
    evt.param1 = param1;
    evt.param2 = param2;
    //FIRE!
    target.dispatchEvent(evt);
}

function foobar(ev) {
    alert("foobar" + ' ' + ev.param1 + ' ' + event.param2);
}

function testEvents(param1) {
    window.addEventListener("foobar", foobar, false); //false to get it in bubble not capture.
    fireEvent("foobar", document, 'test', param1);
}
Run Code Online (Sandbox Code Playgroud)


Chu*_*ars 5

所有的参数 - 就像所有关于事件的其他信息一样 - 应该在Event Object本身内部进行.完全独立的Event Object包含有关该事件的所有必需信息.通常在创建新的自定义事件对象时设置参数值 (而不是在触发事件时).

(以下示例代码的所有片段都与所有其他片段完全匹配.事实上,一些示例可能没有多大意义;每当发生这种情况时,请参考前面的示例片段.)

对于您自己的参数,在某些情况下,您可以重用现有字段(或者甚至可以添加您自己的新字段):

var newEvent = ...
newEvent['scrollX'] = your-own-custom-value;
Run Code Online (Sandbox Code Playgroud)

具体如何设置这些取决于您是否能够使用新的标准化HTML5方式,或者必须回退到较旧的浏览器支持.(即使对于根本不提供任何内容的旧浏览器,添加自定义事件支持的各种"填充程序"也未在此处介绍 - 其中许多将提供自己相当独特的方式来设置参数.)

HTML5方式涉及对象构造函数的"字典"(第二个)参数,如下所示:

var newEvent = new CustomEvent('customname', { propertyname : propertyvalue,
                                            anotherpropname : anotherpropvalue,
                                              thirdpropname : thirdpropvalue,
                                                etcpropname : etcpropvalue }   );
Run Code Online (Sandbox Code Playgroud)

相应的旧方法看起来像这样:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['propertyname'] = propertyvalue;
newEvent['anotherpropname'] = anotherpropvalue;
newEvent['thirdpropname'] = thirdpropvalue;
newEvent['etcpropname'] = etcprovalue;
Run Code Online (Sandbox Code Playgroud)

(上面的例子也可以让HTML5 CustomEvent构造函数实际上更清楚.)

但是,通常不建议使用这样的现有属性名称(或创建自己的属性:-),因为跨浏览器问题和调试麻烦可能非常严重.偶尔这将是必要的,它将起作用,但不要依赖它作为一般技术.尽管某些类型的事件对象包含特定的命名属性,但类似类型的事件对象可能不包括.某些事件属性可能是"只读".事件对象在内部高度可变,从一个浏览器到另一个浏览器甚至浏览器版本之间 创建自己的新属性可能会混淆浏览器的Javascript实现.

相反,使用"预留"的一个特定属性供您在自定义事件中使用,而不是其他任何内容:详细信息.

通常你会有几个参数,但只有一个属性可供你使用.因此,传统的方法是始终将所有参数都变成一个"对象",如下所示:

var myargs = { my : 1,
              own : getElementById('foo');
             args : { X : 32, Y : 53 }    };
Run Code Online (Sandbox Code Playgroud)

HTML5设置此变量的方式如下所示:

var newEvent = new CustomEvent('customname', { bubbles : true,
                                            cancelable : true,
                                                detail : myargs } );
Run Code Online (Sandbox Code Playgroud)

用于执行相同操作的旧界面将类似于:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['detail'] = myargs;
Run Code Online (Sandbox Code Playgroud)

(当然,如果你大量使用Javasript"文字对象"大括号语法来最小化你的输入,你的代码可能看起来与上面的例子略有不同,这些例子优先考虑清晰度.)

(必须始终为每个事件设置两个现有的事件属性,'bubbles'和'cancelable',而不管设置可能的自定义参数.如果使用新的HTML5方式,它们将始终显示为对象中的两个附加行CustomEvent构造函数的第二个参数.如果使用旧方法,它们将是initEvent(...)调用的第二个和第三个参数.)

还提供了两种不同的触发自定义事件的方法.较新的HTML5方式使用object.dispatchEvent(newEvent).旧方法使用object.fireEvent('customname',newEvent,false).这里"对象"表示DOMObject/Element; 究竟是什么(如果有的话)发生如果"对象"是除了DOM元素以外的东西比本主题的其余部分更具浏览器特性.(混合HTML5方式和旧方法通常有效,但可能会令人困惑.另一个经常混淆的问题是拥有一个名为fireEvent(...)的系统函数,并且还使用相同的名称定义自己的函数.)

(触发自定义事件的两种方式之间存在一些神秘的差异.较旧的fireEvent(...)方法要求您重新指定事件的名称,即使您已在initEvent(...)中指定了该事件的名称调用.而较旧的fireEvent(...)方法不会触发"默认操作"[无论这意味着什么].)

另一方面,无论是使用HTML5还是使用旧方法设置事件,都以相同的方式访问自定义参数.它看起来像这样:

function customhandler(evt) {
        alert(evt.detail.own);
Run Code Online (Sandbox Code Playgroud)

如果你的一些自定义值实际上是对象本身,点符号可能会变得很长,看起来像是一个错字......但事实并非如此.例如:

function customhandler(evt) {
        alert(evt.detail.args.X);
Run Code Online (Sandbox Code Playgroud)

但是,在IE 9及以下版本中,其中一些可能会略有不同.希望问题只是尝试重用的常见问题 - 甚至是创建事件对象的属性.如果问题更普遍,你可以在你的网站上放一个"抱歉:-("的消息,或者你可以等待IE6/7/8/9死掉,或者你可以尝试跨浏览器自己破解它,或者你可以使用某种垫片/后备.我不清楚是否最好找到一个"看起来与传统接口完全相同"的垫片,或者使用垫片提供的备用接口来处理所有事情(即使传统接口是可用).

(免责声明:当然我对以上某些内容可能有误...... :-)


nes*_*-EE 5

上面的答案似乎已被弃用。

创建一个新的自定义事件。

var data = { x:20, y:30, rotationY: 60 },
    end = new CustomEvent('MOTION_FINISHED', { detail: data });
    this.dispatchEvent(end);
Run Code Online (Sandbox Code Playgroud)

不过,它似乎只允许属性“detail”传递参数。我还读过“气泡”和“可取消”属性可用,但您在问题中没有提到这些。

要检索您的参数:

function _handler(e){
    var x = (e.detail && e.detail.x) || 0;
}
Run Code Online (Sandbox Code Playgroud)


Mad*_*iha 2

function fireEvent(name, target) {
    //Ready: create a generic event
    var evt = document.createEvent("Events")
    //Aim: initialize it to be the event we want
    evt.initEvent(name, true, true); //true for can bubble, true for cancelable
    //FIRE!
    target.dispatchEvent(evt);
}

function foobar() {
    alert("foobar");
}

function testEvents() {
    window.addEventListener("foobar", foobar, false); //false to get it in bubble not capture.
    fireEvent("foobar", document);
}
Run Code Online (Sandbox Code Playgroud)

用 1 分钟的 Google 搜索找到了这段代码。http://the.unwashedmeme.com/blog/2004/10/04/custom-javascript-events/

  • 而且,您所做的“研究”甚至还没有完成,它不适用于 IE,所以现在我必须进行更多研究。不过还是谢谢你的投票 (2认同)