javascript 触发和捕获自定义事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7057223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 22:49:40  来源:igfitidea点击:

Firing and capturing custom events

javascriptdom-events

提问by André Al?ada Padez

Imagine this scenario (it's really just a scenario):

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

  • I have a global counter that gets incremented on every mouse click.
  • when I reach 50 clicks, I want to fire a custom event named 'reachedCount'
  • I want to register my window object to capture that event with something like
    window.addEventListener('reachedCount', function(args){alert(args.count);}, false)
  • 我有一个全局计数器,每次单击鼠标时都会增加。
  • 当我点击 50 次时,我想触发一个名为“reachedCount”的自定义事件
  • 我想注册我的窗口对象以使用类似的东西捕获该事件
    window.addEventListener('reachedCount', function(args){alert(args.count);}, false)

So, my problems are that I don't know, and can't find anywhere how I can pass arguments to my eventHandler. Also, I had tried the method Rikudo posted, but it doesn't work in IE lt 9.

所以,我的问题是我不知道,也找不到任何地方可以将参数传递给我的 eventHandler。另外,我尝试过 Rikudo 发布的方法,但它在 IE lt 9 中不起作用。

Is this possible? How?

这可能吗?如何?

回答by HBP

Using Rikudo Sennin's answer, you can pass parameters to your event handler by putting them inside the event itself, just like the DOM handlers do!

使用 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);
}

回答by Chuck Kollars

All your arguments -just like all the other information about the event- should be carried inside the Event Object itself. The completely self-contained Event Object carries allthe needed information about that event. Your argument values are generally set when the new custom event object is created(not when the event is fired).

您的所有参数 - 就像有关事件的所有其他信息一样 - 应该包含在事件对象本身中。完全独立的事件对象携带有关该事件的所有所需信息。您的参数值通常在创建新的自定义事件对象时设置 (而不是在触发事件时)。

(Allthe fragments of example code below exactly match allthe other fragments. In fact, some of the examples may not make much sense by themselves; whenever this happens refer to previous example fragments.)

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

For your own arguments, in some cases you could reuse existing fields (or perhaps even add new fields of your own):

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

var newEvent = ...
newEvent['scrollX'] = your-own-custom-value;

Exactly how these would get set differs depending on whether you're able to use the new standardized HTML5 way, or must fall back to older browser support. (The various "shims" that add custom event support even to old browsers that don't provide anything at all aren't covered here -- many of them will provide their own rather unique way to set arguments.)

这些设置的确切方式取决于您是否能够使用新的标准化 HTML5 方式,或者必须回退到旧浏览器支持。(各种“垫片”甚至为根本不提供任何内容的旧浏览器添加自定义事件支持的各种“垫片”在这里没有涵盖——其中许多将提供自己相当独特的设置参数的方式。)

The HTML5 way involves the "dictionary" (second) parameter to the object constructor, something like this:

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

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

The corresponding older method would look something like this:

相应的旧方法如下所示:

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

(The above example may also make it clearer just what the HTML5 CustomEvent constructor is actually doing.)

(上面的例子也可以更清楚地说明 HTML5 CustomEvent 构造函数实际上在做什么。)

Using existing property names like this (or creating your own properties:-), isn't generally recommended though, because cross-browser issues and debugging hassles can be pretty severe. Once in a while this will be necessary and it will work, but don't rely on it as a general technique. Even though some types of event objects include a particular named property, similar types of event objects may not. Some event properties may be "read-only". Event objects are internally highly variable from one browser to another and even between browser versions. And creating your own new properties may confuse the browser's implementation of Javascript.

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

Instead, use the one particular property that's "set aside" for your use in custom events and nothing else: detail.

相反,使用一个“留出”的特定属性供您在自定义事件中使用,而别无其他:detail

Often you will have several arguments, yet there's only one property set aside for your use. So the conventional approach is to always make all your arguments into just one "object", something like this:

通常,您会有多个参数,但只有一个属性可供您使用。因此,传统的方法是始终将所有论点都集中在一个“对象”中,如下所示:

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

The HTML5 way of setting this variable will look something like:

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

var newEvent = new CustomEvent('customname', { bubbles : true,
                                            cancelable : true,
                                                detail : myargs } );

The older interface for doing the same thing will look something like:

用于执行相同操作的旧界面如下所示:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['detail'] = myargs;

(Of course if you make heavy use of the Javasript "literal object" curly brace syntax to minimize your typing, your code may look a little different than the above examples which prioritize clarity.)

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

(Two existing event properties, 'bubbles' and 'cancelable', must always be set for every event, regardless of setting possible custom arguments. If the new HTML5 way is being used, they will always appear as two additional lines in the object that's the second parameter to the CustomEvent constructor. If the older way is being used, they will be the second and third parameters to the initEvent(...) call.)

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

Two different methods of triggering the custom event are also provided. The newer HTML5 way uses object.dispatchEvent(newEvent). The older way uses object.fireEvent('customname', newEvent, false). Here "object" means DOMObject/Element; exactly what (if anything) happens if "object" is something besides a DOM Element is even more browser-specific than the rest of this topic. (Mixing the HTML5 way and the older way generally works, but can be confusing. Another frequent source of confusion is having a system function named fireEvent(...) and also defining your own function with that same name.)

还提供了两种不同的触发自定义事件的方法。较新的 HTML5 方式使用 object.dispatchEvent(newEvent)。旧方法使用 object.fireEvent('customname', newEvent, false)。这里的“对象”是指DOMObject/Element;如果“对象”是 DOM 元素之外的东西,那么究竟会发生什么(如果有的话)比本主题的其余部分更特定于浏览器。(混合 HTML5 方式和旧方式通常有效,但可能会造成混淆。另一个常见的混淆源是有一个名为 fireEvent(...) 的系统函数,并使用相同的名称定义您自己的函数。)

(There are some arcane differences between the two ways of triggering a custom event. The older fireEvent(...) method requires you to re-specify the name of the event even though you already specified it in the initEvent(...) call. And the older fireEvent(...) method does not trigger the "default action" [whatever that means].)

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

On the other side, custom arguments are accessed the same way regardless of whether the HTML5 or the older method of setting up the event was used. It will look something like this:

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

function customhandler(evt) {
        alert(evt.detail.own);

Where some of your custom values are in fact objects themselves, the dot notation can get so long it may look like a typo ...but it's not. For example:

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

function customhandler(evt) {
        alert(evt.detail.args.X);

It appears some of this may work slightly differently in IE 9 and below, though. Hopefully the problems are simply the usual ones with attempting to re-use -or even create- properties of an event object. If problems are more pervasive, you could put a "sorry:-(" message on your website, or you could wait for IE6/7/8/9 to die, or you could try to cross-browser hack it yourself, or you could use some sort of shim/fallback. It's not clear to me whether it's better to find a shim that "looks exactly like" the conventional interface, or to use the alternate interface provided by the shim for everything (even when the conventional interface is available).

不过,似乎其中一些在 IE 9 及更低版本中的工作方式略有不同。希望问题只是尝试重用 - 甚至创建 - 事件对象的属性的常见问题。如果问题更普遍,你可以在你的网站上放一个“sorry:-(”消息,或者你可以等待 IE6/7/8/9 死掉,或者你可以尝试自己跨浏览器破解它,或者你可以使用某种垫片/回退。我不清楚最好是找到一个“看起来完全像”传统界面的垫片,还是使用垫片提供的替代接口来处理所有事情(即使传统接口是可用的)。

(Disclaimer: Of course I could be wrong about some of the above...:-)

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

回答by ness-EE

The answers above seem to be deprecated.

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

Create a new CustomEvent.

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

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

It seems to only allow the property 'detail' to pass parameters though. I've also read 'bubbles' and 'cancelable' properties are available, but you didn't mention those in your question.

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

To retrieve your parameters:

要检索您的参数:

function _handler(e){
    var x = (e.detail && e.detail.x) || 0;
}

回答by Madara's Ghost

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);
}

Found this code with 1 minute of Google Search. http://the.unwashedmeme.com/blog/2004/10/04/custom-javascript-events/

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