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

我已经看过这些问题:

然而,它们都没有回答如何使用 addEventListener获取附加到节点的事件侦听器列表,而不需要在创建事件侦听器之前修改 addEventListener原型。

VisualEvent 不会显示所有事件侦听器(特定于 iphone 的) ,我希望(在某种程度上)以编程方式执行此操作。

162975 次浏览

你不能。

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

DOM4 addEventListener

上面写着

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

意味着将事件侦听器添加到“事件侦听器列表”中。仅此而已。没有关于这个列表应该是什么的概念,也没有关于如何访问它的概念。

Chrome DevTools、 Safari 检查器和 Firebug 支持 < a href = “ https://developers.google.com/web/tools/chrome-devtools/sole/tools # geteventlistener”rel = “ noReferrer”> getEventListener (node)

getEventListeners(document)

您可以使用 $. _ data ($(’[ selector ]’)[0] ,‘ events’)获取所有 jQuery 事件; 将[ selector ]更改为您需要的内容。

有一个插件可以收集 jQuery 附加的所有事件,名为 events sReport。

我也写了我自己的插件,这样做与更好的格式。

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

这似乎是使用 dev 工具查看添加到元素中的事件的最佳方式。

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

更新: 现在我们可以看到 addEventListener 方法添加的事件。

由于没有原生的方法来做到这一点,以下是我发现的较少干扰的解决方案(不要添加任何“旧的”原型方法) :

var ListenerTracker=new function(){
var targets=[];
// listener tracking datas
var _elements_  =[];
var _listeners_ =[];
this.init=function(){
this.listen(Element,window);
};
this.listen=function(){
for(var i=0;i<arguments.length;i++){
if(targets.indexOf(arguments[i])===-1){
targets.push(arguments[i]);//avoid duplicate call
intercep_events_listeners(arguments[i]);
}
}
};
// 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(target){
var _target=target;
if(target.prototype)_target=target.prototype;
if(_target.getEventListeners)return;
if(typeof(_target.addEventListener)!=='function'||typeof(_target.removeEventListener)!=='function'){
console.log('target=',target);
throw('\nListenerTracker Error:\nUnwrappable target.');
}
// backup overrided methods
var _super_={
"addEventListener"      : _target.addEventListener,
"removeEventListener"   : _target.removeEventListener
};


_target["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
var uc=(typeof(useCapture)==='object'?useCapture.useCapture:useCapture)?1:0;
if(!listeners[uc][type])listeners[uc][type]=[];
listeners[uc][type].push({cb:listener,args:arguments});
};
_target["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=(typeof(useCapture)==='object'?useCapture.useCapture:useCapture)?1:0;
if(!listeners[useCapture][type])return;
var lid = listeners[useCapture][type].findIndex(obj=>obj.cb===listener);
if(lid>-1)listeners[useCapture][type].splice(lid,1);
};
_target["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].cb,
"args":list[type][id].args,
"useCapture":!!useCapture
});
}
}
}else{// all
for(var _type in list){
for(var id in list[_type]){
result.push({
"type":_type,
"listener":list[_type][id].cb,
"args":list[_type][id].args,
"useCapture":!!useCapture
});
}
}
}
}
return result;
};
};


}();




ListenerTracker.init();

剪辑

来自@mplugjan 的建议: 修改为监听可包装的目标(singleton | 构造函数)。‘ init’跟踪 元素窗户

例如其他可包装目标:

ListenerTracker.listen(XMLHttpRequest);

来自@kodfire 的建议: 您可能会得到带有 Args属性的可选参数。

我找不到一种方法来使用代码来实现这一点,但是在 Firefox 64中,事件被列在开发工具检查器中每个 HTML 实体的旁边,就像 MDN 的 检查事件侦听器页面上提到的那样,如下图所示:

screen shot of FF Inspector