简体   繁体   English

捕获所有事件(javascript)

[英]Capture all the events (javascript)

I want to be able to capture all events that are both created and dispatched and fire some callback when that happens. 我希望能够捕获所有创建和调度的事件,并在发生这种情况时触发一些回调。

Also, I would like to be able to fire a callback anytime an event is paired with an event listener. 此外,我希望能够在事件与事件监听器配对时随时触发回调。

Problems include: dynamically added elements, events whose propagation or bubbling is prevented, and custom events that are generated dynamically. 问题包括:动态添加的元素,阻止传播或冒泡的事件以及动态生成的自定义事件。 I imagine there would need to be a prototyping of dispatchEvent or something, but I am unsure. 我想有必要对dispatchEvent或其他东西进行原型设计,但我不确定。 Is this even possible? 这甚至可能吗?

Some event basics: 一些事件基础:

  1. Events are dispatched "on" a DOM object (usually an element) that is the event target. 事件被“调度”在作为事件目标的DOM对象(通常是元素)上。
  2. Events can firstly propagate down to child elements in a capture phase. 事件可以首先在捕获阶段向下传播到子元素。 This phase is rarely used since it wasn't supported by some widely used browsers until recently. 这一阶段很少使用,因为直到最近才被一些广泛使用的浏览器所支持。
  3. Events can secondly propagate up to parent elements in a bubbling phase. 事件可以在冒泡阶段第二次传播到父元素。 This phase is commonly used. 这个阶段是常用的。
  4. Some events don't propagate, they have neither a capture or bubble phase (eg focus, blur and submit events). 某些事件不会传播,它们既没有捕获也没有泡沫阶段(例如焦点,模糊和提交事件)。 Some events that propagate in some browsers don't propagate in others. 某些浏览器中传播的某些事件不会在其他浏览器中传播。
  5. DOM elements that respond to events have an event handler. 响应事件的DOM元素具有事件处理程序。 It can be set to listen for particular events and call a listener function when that event reaches the element, either during capture, bubbling or if the element is an event target. 它可以设置为侦听特定事件,并在该事件到达元素时调用侦听器函数,在捕获,冒泡或元素是事件目标期间。
  6. Listeners can cancel propagation, eg a click event on a span inside a link can cancel propagation so the link doesn't get the click 监听器可以取消传播,例如链接内的跨度上的单击事件可以取消传播,因此链接不会获得点击

Given the above, it is a practical impossibility to "capture all events" using the Events API . 鉴于上述情况,使用Events API “捕获所有事件”实际上是不可能的。 It would require establishing a listener for every event type on every element and be impossible to capture custom events because you have to know about them to set an appropriate listener. 它需要为每个元素上的每个事件类型建立一个监听器,并且不可能捕获自定义事件,因为您必须知道它们以设置适当的监听器。

I imagine there would need to be a prototyping of dispatchEvent or something 我想有必要对dispatchEvent或其他东西进行原型设计

dispatchEvent is a method of an Event instance, it's not specified to be a constructor (there is no requirement for it to have an internal [[Construct]] method) so not practical to use as such. dispatchEvent是一个Event实例的方法,它没有被指定为构造函数(没有要求它有一个内部的[[Construct]]方法)因此不实用。 Browsers aren't required to implement prototype inheritance for host objects (though most do), and the implementation details of host objects and methods are largely hidden, so this is not an option. 浏览器不需要为宿主对象实现原型继承(尽管大多数都是这样),并且宿主对象和方法的实现细节在很大程度上是隐藏的,因此这不是一个选项。

You might try extending the Event API, but you really should not mess with host objects . 您可以尝试扩展Event API,但实际上您不应该使用宿主对象

It seems that you are concerned about dynamically added elements. 您似乎关注动态添加的元素。 There is a strategy called " event delegation " , where you work out the events you need to listen for, then setup listeners as close to the event targets as you can on an element that doesn't change (eg a table element if you are dynamically adding and removing table rows, or a container div for other elements) for the specific event types you need to respond to. 有一个名为事件委托的策略,您可以在其中计算出需要监听的事件,然后将侦听器设置为尽可能接近事件目标,而不是更改的元素(例如,如果是为需要响应的特定事件类型动态添加和删除表行或其他元素的容器div。

You can also have the functions that are modifying the DOM dispatch custom events to add listeners or whatever. 您还可以使用修改DOM调度自定义事件的函数来添加侦听器或其他任何内容。

If you really want to do this, then you can override addEventListener to keep track of events being registered and fired. 如果您确实想这样做,那么您可以覆盖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; }
    };

}());

However, there are uncountable reasons not to do this, not least the fact that you will quickly run out of memory as you record thousands of events such as mouse moves. 但是,有不可原谅的理由不这样做,尤其是当您记录数千个事件(如鼠标移动)时,您将很快耗尽内存。 This will also not capture event listeners set in ways such as elt.onclick . 这也不会捕获以elt.onclick等方式设置的事件侦听elt.onclick Nor of course will it catch listeners set up via the old IE attachEvent API. 它当然也不会捕获通过旧的IE attachEvent API设置的侦听器。 Most importantly, it will not help with you that events that are generated and listened for internally, such as a mouse click on a check box. 最重要的是,在内部生成和监听的事件(例如鼠标单击复选框)对您没有帮助。 (A complete solution would also require handling removeEventListener .) (完整的解决方案还需要处理removeEventListener 。)

You can also override createEvent and dispatch in similar fashion, but again, that will capture only events that are explicitly created or dispatched in the JS code. 您也可以以类似的方式覆盖createEventdispatch ,但同样,它将仅捕获在JS代码中显式创建或分派的事件。

If you really want to do what you seem to be wanting to, I guess you need to fork Chrome. 如果你真的想做你想做的事,我想你需要分叉Chrome。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM