捕获所有事件(javascript)

时间:2014-09-06 01:16:41

标签: javascript javascript-events

我希望能够捕获所有创建和调度的事件,并在发生这种情况时触发一些回调。

此外,我希望能够在事件与事件监听器配对时随时触发回调。

问题包括:动态添加的元素,阻止传播或冒泡的事件以及动态生成的自定义事件。我想有必要对dispatchEvent或其他东西进行原型设计,但我不确定。这甚至可能吗?

2 个答案:

答案 0 :(得分:3)

一些事件基础知识:

  1. 事件被“调度”在作为事件目标的DOM对象(通常是元素)上。
  2. 事件可以首先在捕获阶段向下传播到子元素。这个阶段很少使用,因为直到最近才被一些广泛使用的浏览器支持。
  3. 事件可以在冒泡阶段第二次传播到父元素。这个阶段很常用。
  4. 某些事件不会传播,它们既没有捕获也没有泡沫阶段(例如焦点,模糊和提交事件)。某些浏览器中传播的某些事件不会在其他浏览器中传播。
  5. 响应事件的DOM元素具有事件处理程序。它可以设置为侦听特定事件,并在该事件到达元素时调用侦听器函数,无论是在捕获,冒泡还是元素是事件目标时。
  6. 听众可以取消传播,例如链接内的跨度上的单击事件可以取消传播,因此链接不会获得单击
  7. 鉴于上述情况,使用Events API“捕获所有事件”实际上是不可能的。它需要为每个元素的每个事件类型建立一个监听器,并且不可能捕获自定义事件,因为你必须知道它们才能设置一个合适的监听器。

      

    我想有必要对 dispatchEvent 或其他东西进行原型设计

    dispatchEvent是一个Event实例的方法,它没有被指定为构造函数(没有要求它有一个内部[[Construct]]方法)因此不实用。浏览器不需要为宿主对象实现原型继承(尽管大多数都是这样),并且宿主对象和方法的实现细节在很大程度上是隐藏的,所以这不是一个选项。

    您可以尝试扩展Event API,但您确实should not mess with host objects

    您似乎关注动态添加的元素。有一个名为"event delegation"的策略,您可以在其中计算出需要监听的事件,然后将侦听器设置为尽可能接近事件目标,而不是更改的元素(例如,如果你是一个表元素)为您需要响应的特定事件类型动态添加和删除表行或其他元素的容器div。

    您还可以使用修改DOM调度自定义事件的函数来添加侦听器或其他任何内容。

答案 1 :(得分:2)

如果您真的想这样做,那么您可以覆盖addEventListener以跟踪正在注册和触发的事件。

var myEventManager = (function() {
    var old = EventTarget.prototype.addEventListener,
        listeners = [],
        events = [];

    EventTarget.prototype.addEventListener = function(type, listener) {

        function new_listener(listener) {
            return function(e) {
                events.push(e);                  // remember event
                return listener.call(this, e);   // call original listener
            };
        }

        listeners.push([type, listener]);        // remember call
        return old.call(this, type, new_listener(listener));  // call original
    };

    return {
        get_events: function() { return events; },
        get_listeners: function() {return listeners; }
    };

}());

但是,有不可原谅的理由不这样做,尤其是当您记录数千个事件(如鼠标移动)时,您将很快耗尽内存。这也不会捕获以elt.onclick等方式设置的事件侦听器。它当然也不会捕获通过旧的IE attachEvent API设置的监听器。最重要的是,在内部生成和监听的事件(例如鼠标单击复选框)对您没有帮助。 (完整的解决方案还需要处理removeEventListener。)

您也可以以类似的方式覆盖createEventdispatch,但同样只会捕获在JS代码中显式创建或分派的事件。

如果你真的想做你想做的事,我想你需要分叉Chrome。