检查任何DOM元素的附加事件处理程序

时间:2010-04-12 15:16:34

标签: javascript events

有没有办法查看哪些函数/代码附加到DOM元素的任何事件?使用Firebug或任何其他工具。

7 个答案:

答案 0 :(得分:72)

自2011年中期Chrome发布以及自2010年以来Chrome开发者频道发布以来,Elements Panel in Google Chrome Developer tools已经出现过这种情况。

此外,为所选节点显示的事件侦听器按照它们被触发的顺序通过捕获和冒泡阶段

在Mac OSX上按命令 + 选项 + i Ctrl + Shift + i 可以在Chrome中启动它

dev tools screenshot

答案 1 :(得分:68)

使用传统的element.onclick= handler或HTML <element onclick="handler">附加的事件处理程序可以从脚本或调试器中的element.onclick属性中轻松检索。

目前无法从脚本中检索使用DOM Level 2 Events addEventListener方法和IE attachEvent附加的事件处理程序。 DOM Level 3曾经提出element.eventListenerList来获取所有听众,但目前还不清楚这是否会达到最终规范。今天在任何浏览器中都没有实现。

作为浏览器扩展的调试工具可以访问这些类型的侦听器,但我不知道实际上有什么。

一些JS框架留下了足够的事件绑定记录来计算出他们一直在做的事情。 Visual Event采用这种方法来发现通过一些流行框架注册的监听器。

答案 2 :(得分:6)

您可以通过查看DOM来查看直接附加的事件(element.onclick = handler)。 您可以使用FireBug和FireQuery在Firefox中查看jQuery附加事件。似乎没有办法使用FireBug查看添加addEventListener的事件。但是,您可以使用Chrome调试程序在Chrome中查看它们。

答案 3 :(得分:6)

您可以使用Allan Jardine的Visual Event来检查页面上几个主要JavaScript库中所有当前连接的事件处理程序。它适用于jQuery,YUI和其他几个。

Visual Event是一个JavaScript书签,因此与所有主流浏览器兼容。

答案 4 :(得分:6)

Chrome开发工具最近宣布了Monitoring JavaScript Events的一些新工具。

  

<强> TL; DR

     

使用unmonitorEvents()收听某种类型的事件。

     

使用getEventListeners()停止收听。

     

使用getEventListeners()获取DOM元素的监听器。

     

使用“事件侦听器”检查器面板获取有关事件侦听器的信息。

查找自定义事件

根据我的需要,在第三方代码中发现自定义JS事件,以下两个版本的getEventListeners(window)非常有用;

  • getEventListeners(document)
  • window

如果您知道事件监听器附加到哪个DOM节点,则传递该节点,而不是documentclick

已知事件

如果您知道要监控的事件,例如文档正文中的monitorEvents(document.body, 'click');您可以使用以下内容:document.body

您现在应该开始看到控制台中记录的package main import ( "log" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/sqlite" _ "github.com/mattn/go-sqlite3" ) type Business struct { ID uint Name string `gorm:"not null"` Tables Tables `gorm:"ForeignKey:BusinessID"` } type Table struct { ID uint Ref string `gorm:"not null"` Business Business BusinessID uint } type Tables []Table type Businesses []Business func main() { var err error var db *gorm.DB db, err = gorm.Open("sqlite3", "test.db") if err != nil { log.Fatal(err) } defer db.Close() db.LogMode(true) db.AutoMigrate(&Business{}) db.AutoMigrate(&Table{}) bus := Business{ Name: "Test", Tables: Tables{ Table{Ref: "A1"}, }, } db.Create(&bus) var businesses Businesses db.Preload("Tables").Find(&businesses) log.Println(businesses) } 上的所有点击事件。

答案 5 :(得分:1)

我很好奇@Rolf的方法是否真的有效。请记住,这是用包装的标准版本替换标准HTMLElement.prototype.addEventLister()的“粗暴”方法。显然,这只能是“用于测试的注入方法”,对于接近“生产版本”的任何事物,绝对必须删除。

测试时,我发现,除了小故障(他的e在任何地方都没有定义,但可以很容易地用this代替)之外,方法也可以工作,只要

  • 您一直在实际元素本身上addEventListener()仅使用
  • ,如果您不使用委派的事件附件
  • 通过设置onclickoninput之类的属性来
  • 直接事件分配

我继续找出“嗅探”是否可以通用一些,并提出了以下修改版本:

(nativeMethod=>{ // IIFE-closure to manipulate the standard addEventListener method:
  HTMLElement.prototype.addEventListener = function (type,fun) {
    (this.ELL=this.ELL||[]).push([type,fun]);
    nativeMethod.call(this,type,fun);
  }
})(HTMLElement.prototype.addEventListener);

// LIST direct and indirect event attachments for element `el`:
function listELfor(el){ 
  const events="click,change,input,keyup,keydown,blur,focus,mouseover,mouseout"
        .split(",").map(e=>"on"+e);  // possible direct event assignments to check up on
  const evlist = (el.ELL||[]).map(([t,f])=>[t,f.toString()]); 
  events.forEach(e=> el[e] && (evlist[e]=[e.substr(2),el[e].toString()]) )
  let p=el.parentNode;
  if (p.tagName!=="HTML"){  // if available: run function on parent level recursively:
    evlist[p.tagName+(p.id?'#'+p.id:'')+(p.className?'.'+p.className:'')]=listELfor(el.parentNode);    
  }
  return evlist;
};

// ============ TESTING ==========================================
// now, let's do some sample event attachments in different ways:
const sp=document.querySelector('h1 span');  // sp = the target SPAN within H1
sp.addEventListener('click',function(e){console.log('first:',e.target)});
sp.addEventListener('click',function(e){console.log('second:',e.target.tagName)});
sp.addEventListener('click',function(e){console.log('third:',e.target.dataset.val)});
// attach an event to the parent node (H1):
sp.parentNode.addEventListener('click',function(e){console.log('Click event attached to H1, click-target is',e.target.tagName);});

// and finally, let's also assign an onclick event directly by using the ONCLICK attribute:
sp.onclick=e=>console.log('direct onclick on span, text:',e.target.textContent);

// Get all event handler functions linked to `sp`?
const allHandlers=listELfor(sp);
for (id in allHandlers) console.log(id,allHandlers[id]);
h1 span {cursor:pointer}
.as-console-wrapper {max-height:85% !important}
<div id="main-frame-error" class="interstitial-wrapper">
    <div id="main-content">
      <div class=""></div>
      <div id="main-message">
        <h1>Hello, <span data-val="123">THESE WORDS ARE CLICKABLE</span></h1>
        <p>Some more text here to pad it out. This text should be unresponsive.</p>
      </div>
    </div>
</div>

IIFE结构将.addEventListener()函数处理程序附件捕获为数组存储在相关DOM元素的ELL属性中。然后,函数listELfor(el)拾取元素本身的这些函数处理程序,并向上移动父级层次结构以获取对其父级的赋值。该功能还将处理使用onclick和类似属性的直接事件分配。

listELfor()将返回具有额外属性的数组对象。这些属性将不必要在纯console.log()中可见。这就是我使用for (id in allHandlers)循环的原因。

请注意:
Chrome 还将列出这些“额外的” Array属性-甚至还有与父级及其父级的父级事件附件相关的其他属性,如下所示: enter image description here

答案 6 :(得分:0)

您可以扩展您的javascript环境以跟踪事件侦听器。使用一些代码包装(或“重载”#)本机addEventListener()方法,该代码可以保留从那时起添加的任何事件侦听器的记录。您还必须扩展HTMLElement.prototype.removeEventListener以保留准确反映DOM中发生的事情的记录。

仅仅是为了说明(未经测试的代码) - 这是一个如何包装&#39; addEventListener,用于在对象本身上记录已注册的事件侦听器:

var nativeMethod = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function (type, listener) {
   var el = e.currentTarget;
   if(!(el.eventListeners instanceof Array)) { el.eventListeners = []}
   el.eventListeners.push({'type':type, 'listener':listener});
   nativeMethod.call(el, type, listener);
}
相关问题