触发和捕获自定义事件

时间:2011-08-14 13:57:36

标签: javascript javascript-events

想象一下这种情况(实际上只是一个场景):

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

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

这可能吗?如何?

4 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:5)

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

All 以下示例代码的片段完全匹配 all 其他片段。事实上,有些示例可能没有多大意义;只要发生这种情况参考前面的示例片段。)

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

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

这些设置的具体方式会有所不同,具体取决于您是否能够使用新的标准化HTML5方式,或者必须回退到较旧的浏览器支持。 (各种"垫片"即使对于那些根本不提供任何东西的旧浏览器也添加了自定义事件支持 - 这里没有提供 - 其中许多将提供他们自己的独特方式设置参数。)

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

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

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

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

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

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

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

通常你会有几个论点,但是只有一个属性留给你使用。因此,传统的方法是始终将所有参数都放入一个"对象",如下所示:

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

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

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

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

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

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

(无论是否设置了可能的自定义参数,都必须始终为每个事件设置两个现有的事件属性,' bubbles'和#39; 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);

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

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

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

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

答案 2 :(得分:3)

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

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

答案 3 :(得分:3)

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

创建一个新的CustomEvent。

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

似乎只允许属性'detail'传递参数。我也读过“气泡”和“可取消”的属性,但你没有提到你的问题。

检索参数:

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