调试时或从JavaScript代码中如何在DOM节点上查找事件侦听器?

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

使用以下事件附加事件:

  1. Prototype的 Event.observe ;
  2. DOM的addEventListener
  3. 作为元素属性element.onclick
乐卡卡西2020/03/10 12:20:42

更改这些功能将允许您记录添加的侦听器:

EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent

阅读其他的听众

console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));
LEYTom西门2020/03/10 12:20:42

存在一个不错的jQuery Events扩展

在此处输入图片说明 (主题来源

HarryGil2020/03/10 12:20:42

Opera 12(不是基于最新的Chrome Webkit引擎的)Dragonfly已经有一段时间了,并且显然显示在DOM结构中。在我看来,它是出色的调试器,也是我仍然使用基于Opera 12的版本的唯一原因(不存在基于v13,v14的版本,基于v15 Webkit的版本仍然缺少Dragonfly)

在此处输入图片说明

斯丁Jim2020/03/10 12:20:42

如果您拥有Firebug,则可以用来console.dir(object or array)在控制台日志中打印任何JavaScript标量,数组或对象的一棵漂亮的树。

尝试:

console.dir(clickEvents);

要么

console.dir(window);
西门小卤蛋2020/03/10 12:20:42

完全有效的解决方案基于Jan Turon的回答 -行为类似于getEventListeners()控制台:

(有一个重复的小错误。无论如何它不会破坏太多。)

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._addEventListener(a,b,c);
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(!this.eventListenerList[a])
      this.eventListenerList[a] = [];
    //this.removeEventListener(a,b,c); // TODO - handle duplicates..
    this.eventListenerList[a].push({listener:b,useCapture:c});
  };

  Element.prototype.getEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined)
      return this.eventListenerList;
    return this.eventListenerList[a];
  };
  Element.prototype.clearEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined){
      for(var x in (this.getEventListeners())) this.clearEventListeners(x);
        return;
    }
    var el = this.getEventListeners(a);
    if(el==undefined)
      return;
    for(var i = el.length - 1; i >= 0; --i) {
      var ev = el[i];
      this.removeEventListener(a, ev.listener, ev.useCapture);
    }
  };

  Element.prototype._removeEventListener = Element.prototype.removeEventListener;
  Element.prototype.removeEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._removeEventListener(a,b,c);
      if(!this.eventListenerList)
        this.eventListenerList = {};
      if(!this.eventListenerList[a])
        this.eventListenerList[a] = [];

      // Find the event in the list
      for(var i=0;i<this.eventListenerList[a].length;i++){
          if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
              this.eventListenerList[a].splice(i, 1);
              break;
          }
      }
    if(this.eventListenerList[a].length==0)
      delete this.eventListenerList[a];
  };
})();

用法:

someElement.getEventListeners([name]) -返回事件侦听器的列表,如果设置了名称,则返回该事件的侦听器数组

someElement.clearEventListeners([name]) -删除所有事件侦听器,如果设置了名称,则仅删除该事件的侦听器

TomMandy2020/03/10 12:20:42

Firefox开发人员工具现在可以执行此操作。通过单击每个元素显示右侧的“ ev”按钮来显示事件,包括jQueryDOM事件。

检查器选项卡中Firefox开发人员工具的事件侦听器按钮的屏幕截图

别坑我路易2020/03/10 12:20:42

您可以将本机DOM方法包装在事件顶部,以管理事件侦听器<head>

<script>
    (function(w){
        var originalAdd = w.addEventListener;
        w.addEventListener = function(){
            // add your own stuff here to debug
            return originalAdd.apply(this, arguments);
        };

        var originalRemove = w.removeEventListener;
        w.removeEventListener = function(){
            // add your own stuff here to debug
            return originalRemove.apply(this, arguments);
        };
    })(window);
</script>

H / T @ les2

伽罗路易2020/03/10 12:20:42

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

凯LEY2020/03/10 12:20:42

1:Prototype.observe使用Element.addEventListener(请参见源代码

2:您可以重写Element.addEventListener以记住添加的侦听器(handy属性EventListenerList已从DOM3规范建议中删除)。在附加任何事件之前运行以下代码:

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    this._addEventListener(a,b,c);
    if(!this.eventListenerList) this.eventListenerList = {};
    if(!this.eventListenerList[a]) this.eventListenerList[a] = [];
    this.eventListenerList[a].push(b);
  };
})();

通过以下方式阅读所有事件:

var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

并且不要忘记重写Element.removeEventListener以从定制中删除事件Element.eventListenerList

3:在Element.onclick这里酒店需要特别注意:

if(someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4:别忘了Element.onclickcontent属性:这是两件事:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

因此,您也需要处理它:

var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);

Visual Event书签(在最流行的答案中提到)仅窃取自定义库处理程序缓存:

It turns out that there is no standard method provided by the W3C recommended DOM interface to find out what event listeners are attached to a particular element. While this may appear to be an oversight, there was a proposal to include a property called eventListenerList to the level 3 DOM specification, but was unfortunately been removed in later drafts. As such we are forced to looked at the individual Javascript libraries, which typically maintain a cache of attached events (so they can later be removed and perform other useful abstractions).

As such, in order for Visual Event to show events, it must be able to parse the event information out of a Javascript library.

元素覆盖可能存在问题(即,由于存在一些特定于DOM的特定功能,例如实时集合,无法在JS中进行编码),但是它原生提供了eventListenerList支持,并且可以在Chrome,Firefox和Opera中使用(不适用于IE7) )。

Near小哥神奇2020/03/10 12:20:42

可以用JavaScript 列出所有事件侦听器您只需修改prototypeHTML元素的方法(添加侦听器之前)。

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属性,该属性包含其所有侦听器。它甚至可以删除带有匿名功能的侦听器。

小胖路易神无2020/03/10 12:20:42

getEventListeners(domElement)开发人员工具控制台中支持Chrome,Firefox,Vivaldi和Safari

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

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

斯丁村村GO2020/03/10 12:20:42

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

Update: Visual Event 2 available.