使用addEventListener获取附加到节点的事件侦听器


106

我已经看过以下问题:

但是,它们都没有回答如何使用创建连接到节点的事件侦听器的列表addEventListener,而不addEventListener在创建事件侦听器之前修改原型。

VisualEvent不会显示所有事件侦听器(特定于iPhone的事件侦听器),而我想以编程方式(某种程度上)做到这一点。



“有些编程方式”,并且该问题的公认答案是devtools功能,这一事实使它成为所列问题的重复。对于那些正在寻找JS解决方案的人,答案是“没有一个”
Nickolay

Answers:



65

你不能

获取连接到节点的所有事件侦听器的列表的唯一方法是拦截侦听器附件调用。

DOM4 addEventListener

将事件侦听器追加到类型设置为type的事件侦听器的关联列表,将侦听器设置为侦听器的捕获和将捕获设置为捕获的捕获,除非该列表中已经存在具有相同类型,侦听器和捕获的事件侦听器。

意味着将事件侦听器添加到“事件侦听器列表”中。就这样。没有关于此列表应该是什么以及您应该如何访问它的概念。


12
是否有任何理由为其必须以这种方式工作提供理由或理由?显然,浏览器知道所有侦听器是什么。
Darth Egregious

3
@ user973810:您如何让他证明这一点?DOM API没有提供执行此操作的方法,在当前的浏览器中也没有非标准的方法可以执行此操作。至于为什么会这样,我真的不知道。想做的事似乎很合理。
Tim Down'4

我已经看到了一些关于为此添加API到DOM的线程。
Raynos 2012年

@TimDown编辑帮助。看到没有诸如“ getEventListeners”之类的规范,这说明了为什么没有这种规范是有道理的。
Darth Egregious

24

由于没有本地方法可以执行此操作,因此我发现的侵入性较小(不要添加任何“旧”原型方法):

var ListenerTracker=new function(){
    var is_active=false;
    // listener tracking datas
    var _elements_  =[];
    var _listeners_ =[];
    this.init=function(){
        if(!is_active){//avoid duplicate call
            intercep_events_listeners();
        }
        is_active=true;
    };
    // register individual element an returns its corresponding listeners
    var register_element=function(element){
        if(_elements_.indexOf(element)==-1){
            // NB : split by useCapture to make listener easier to find when removing
            var elt_listeners=[{/*useCapture=false*/},{/*useCapture=true*/}];
            _elements_.push(element);
            _listeners_.push(elt_listeners);
        }
        return _listeners_[_elements_.indexOf(element)];
    };
    var intercep_events_listeners = function(){
        // backup overrided methods
        var _super_={
            "addEventListener"      : HTMLElement.prototype.addEventListener,
            "removeEventListener"   : HTMLElement.prototype.removeEventListener
        };

        Element.prototype["addEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["addEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=useCapture?1:0;

            if(!listeners[useCapture][type])listeners[useCapture][type]=[];
            listeners[useCapture][type].push(listener);
        };
        Element.prototype["removeEventListener"]=function(type, listener, useCapture){
            var listeners=register_element(this);
            // add event before to avoid registering if an error is thrown
            _super_["removeEventListener"].apply(this,arguments);
            // adapt to 'elt_listeners' index
            useCapture=useCapture?1:0;
            if(!listeners[useCapture][type])return;
            var lid = listeners[useCapture][type].indexOf(listener);
            if(lid>-1)listeners[useCapture][type].splice(lid,1);
        };
        Element.prototype["getEventListeners"]=function(type){
            var listeners=register_element(this);
            // convert to listener datas list
            var result=[];
            for(var useCapture=0,list;list=listeners[useCapture];useCapture++){
                if(typeof(type)=="string"){// filtered by type
                    if(list[type]){
                        for(var id in list[type]){
                            result.push({"type":type,"listener":list[type][id],"useCapture":!!useCapture});
                        }
                    }
                }else{// all
                    for(var _type in list){
                        for(var id in list[_type]){
                            result.push({"type":_type,"listener":list[_type][id],"useCapture":!!useCapture});
                        }
                    }
                }
            }
            return result;
        };
    };
}();
ListenerTracker.init();

您还应使其拦截窗口事件侦听器。除此之外,这很棒!

2

您可以使用$ ._ data($('([selector]')[0],'events');获得所有jQuery事件。将[选择器]更改为所需的内容。

有一个插件可以收集jQuery附加的所有事件,称为eventsReport。

我也写自己的插件,以更好的格式做到这一点。

但是无论如何,我们似乎无法收集addEventListener方法添加的事件。也许可以包装addEventListener调用来存储在包装调用之后添加的事件。

似乎是使用开发工具查看事件添加到元素中的最佳方法。

但是您在那里看不到委托事件。因此,我们需要jQuery eventsReport。

更新:现在我们可以看到由addEventListener方法添加的事件,请参见此问题。


这是一个私有且已弃用的界面,可能很快就会消失,因此请不要依赖它。
mgol 2014年

1
是的,但是我回答的时候,开发工具中没有这种能力。因此,没有任何选择。
Rantiev 2014年

@Rantiev已弃用,您可以删除该答案吗?
朱利奥·马林斯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.