如何在 JavaScript 或调试中在 DOM 节点上找到事件侦听器?

IT技术 javascript events dom
2021-01-15 23:17:08

我有一个页面,其中一些事件侦听器附加到输入框和选择框。有没有办法找出哪些事件侦听器正在观察特定的 DOM 节点以及针对什么事件?

事件附加使用:

  1. 原型的 Event.observe;
  2. DOM 的addEventListener
  3. 作为元素属性element.onclick
6个回答

如果您只需要检查页面上发生的事情,您可以尝试Visual Event书签。

更新Visual Event 2可用。

完美的!击败 Firebug 的EventBug插件。
2021-03-10 23:17:08
我相信提到的 Chrome 扩展程序 @ssharma 是这里可用的
2021-03-18 23:17:08
Chrome 和 FF 内部开发者工具 (F12) 具有内置事件查看器!Chrome:在“元素”选项卡上,选择元素并查看右侧有:样式、计算、事件侦听器
2021-03-18 23:17:08
如果页面引用第三方 js 库,则 Visial 事件不起作用。它引发了一个错误: XMLHttpRequest 无法加载A.com/js/jquery-ui-1.10.3.custom.js?_=1384831682813Access-Control-Allow-Origin 不允许Origin B.com
2021-04-03 23:17:08
这向页面添加了数以百万计的元素,其中许多是图像。在具有许多事件处理程序的页面上,它的实用性大大降低(我的有 17k,加载 Visual Event 大约需要 3 分钟)。
2021-04-06 23:17:08

Chrome、Firefox、Vivaldi 和 SafarigetEventListeners(domElement)在其开发人员工具控制台中支持

对于大多数调试目的,可以使用它。

以下是使用它的非常好的参考:https : //developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners

不错,但只能在 Chrome 控制台的命令行中使用 :(
2021-03-11 23:17:08
提示:getEventListeners($0)将获取您在 Chrome 开发工具中关注的元素的事件侦听器。我经常用这个。喜欢不必使用 querySelector 或 get__By_ 函数
2021-03-14 23:17:08
如果您解释了如何获取事件侦听器的源代码,您本可以为我节省 3 个小时。那个“参考”没有解释任何事情。万一别人是在亏损方法如下:var list = getEventListeners(document.getElementById("YOURIDHERE")); console.log(list["focus"][0]["listener"].toString())如果同一事件有多个侦听器,则将“焦点”更改为要检查的事件和数量。
2021-03-18 23:17:08
+1。特定于浏览器的代码对我来说不是问题,因为我试图让一个我无法控制的页面正常工作。
2021-03-24 23:17:08
@Raghav 啊谢谢,用法不是:正如我最初想到的:)getEventListeners(object) obj getEventListeners()
2021-03-27 23:17:08

这取决于事件的附加方式。为了说明,假设我们有以下点击处理程序:

var handler = function() { alert('clicked!') };

我们将使用不同的方法将它附加到我们的元素上,有些允许检查,有些不允许。

方法 A) 单个事件处理程序

element.onclick = handler;
// inspect
console.log(element.onclick); // "function() { alert('clicked!') }"

方法 B) 多个事件处理程序

if(element.addEventListener) { // DOM standard
    element.addEventListener('click', handler, false)
} else if(element.attachEvent) { // IE
    element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers

方法 C):jQuery

$(element).click(handler);
  • 1.3.x

     // inspect
     var clickEvents = $(element).data("events").click;
     jQuery.each(clickEvents, function(key, value) {
         console.log(value) // "function() { alert('clicked!') }"
     })
    
  • 1.4.x(将处理程序存储在一个对象中)

     // inspect
     var clickEvents = $(element).data("events").click;
     jQuery.each(clickEvents, function(key, handlerObj) {
         console.log(handlerObj.handler) // "function() { alert('clicked!') }"
         // also available: handlerObj.type, handlerObj.namespace
     })
    
  • 1.7+(非常好)

    使用此评论中的知识制作

     events = $._data(this, 'events');
     for (type in events) {
       events[type].forEach(function (event) {
         console.log(event['handler']);
       });
     }
    

(见jQuery.fn.datajQuery.data

方法 D):原型(凌乱)

$(element).observe('click', handler);
  • 1.5.x

     // inspect
     Event.observers.each(function(item) {
         if(item[0] == element) {
             console.log(item[2]) // "function() { alert('clicked!') }"
         }
     })
    
  • 1.6 到 1.6.0.3,包括(这里非常困难)

     // inspect. "_eventId" is for < 1.6.0.3 while 
     // "_prototypeEventID" was introduced in 1.6.0.3
     var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
     clickEvents.each(function(wrapper){
         console.log(wrapper.handler) // "function() { alert('clicked!') }"
     })
    
  • 1.6.1(好一点)

     // inspect
     var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
     clickEvents.each(function(wrapper){
         console.log(wrapper.handler) // "function() { alert('clicked!') }"
     })
    

单击控制台中的结果输出(显示函数的文本)时,控制台将直接导航到相关 JS 文件中函数声明的行。

@Jan,这似乎不适用于 jQuery 1.7.2,该版本有不同的方法吗?
2021-03-15 23:17:08
在“方法 B”(addEventListener)上,这里有一个关于使用纯 DOM 事件 API 注册的处理程序的枚举设施状态的答案:stackoverflow.com/questions/7810534/...
2021-03-16 23:17:08
感谢更新这个。不幸的是,您必须遍历每种类型的处理程序。
2021-03-27 23:17:08
@约翰:感谢您的评论。您有一个“真正的 JavaScript”示例来获取之前通过addEventListener?
2021-03-28 23:17:08
@tomdemuyt 在 jQuery 中,事件现在存储在内部数据数组中,而不是.data('events')像以前那样可以通过访问要访问内部事件数据,请使用$._data(elem, 'events'). 请注意,此函数在 jQuery 源代码中被标记为“仅供内部使用”,因此不能保证它在未来始终有效,但我相信它自 jQuery 1.7 以来一直有效并且仍然有效。
2021-04-02 23:17:08

Chrome 或 Safari 浏览器中的 WebKit Inspector 现在可以执行此操作。当您在 Elements 窗格中选择它时,它将显示 DOM 元素的事件侦听器。

这让我大吃一惊,一些遗留原型代码在同一元素上绑定了多个函数,我迫不及待地试图追踪它们。非常感谢伊山。
2021-03-27 23:17:08
我不确定它是否显示了所有的事件处理程序;只是单个 HTML 事件处理程序。
2021-04-02 23:17:08
为了完整性,我应该提到 Firebug 的 EventBug 插件 < softwareihard.com/blog/category/eventbug >
2021-04-06 23:17:08

可以在 JavaScript 中列出所有事件侦听器:这并不难;您只需要破解prototypeHTML 元素's 方法(添加侦听器之前)。

function reportIn(e){
    var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
    console.log(a)
}


HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;

HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
    this.realAddEventListener(a,reportIn,c); 
    this.realAddEventListener(a,b,c); 
    if(!this.lastListenerInfo){  this.lastListenerInfo = new Array()};
    this.lastListenerInfo.push({a : a, b : b , c : c});
};

现在每个锚元素 ( a) 都有一个lastListenerInfo属性,其中包含它的所有侦听器。它甚至适用于使用匿名函数删除侦听器。

这是非常无用的 - 它显示添加了哪些 eventListeners,这在某些情况下可能很好,但不显示删除了什么。因此,如果您试图调试已删除的内容和未删除的内容,则根本没有办法。
2021-03-13 23:17:08
@IvanCastellanos 我的意思是你的 lastListenerInfo 数组包含添加的监听器OP 询问哪些事件侦听器正在观察特定的 DOM 节点,其中包括已删除的那些如果你已经覆盖removeEventListener了你对addEventListenerlastListenerInfo 数组所做的同样的事情,那将完全符合 OP 的要求(尽管他在谈论输入和选择元素,而不是锚点,但无论如何)。
2021-03-13 23:17:08
如果您正在编写用户脚本或内容脚本,则此方法将不起作用。这些天不仅可能被沙箱化,而且你如何保证执行顺序?
2021-03-14 23:17:08
你不能直接修改Node.prototype吗?无论如何,这就是HTMLAnchorElement继承的地方.addEventListener
2021-03-29 23:17:08
您假设用户代理实现了 DOM 主机对象的原型继承并允许您修改它们。这些都不是好主意:不要修改您不拥有的对象
2021-03-29 23:17:08