有没有办法查看哪些函数/代码附加到DOM元素的任何事件?使用Firebug或任何其他工具。
答案 0 :(得分:72)
自2011年中期Chrome发布以及自2010年以来Chrome开发者频道发布以来,Elements Panel in Google Chrome Developer tools已经出现过这种情况。
此外,为所选节点显示的事件侦听器按照它们被触发的顺序通过捕获和冒泡阶段。
在Mac OSX上按命令 + 选项 + i 并 Ctrl + Shift + i 可以在Chrome中启动它
答案 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节点,则传递该节点,而不是document
或click
。
已知事件
如果您知道要监控的事件,例如文档正文中的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()
仅使用 onclick
或oninput
之类的属性来我继续找出“嗅探”是否可以通用一些,并提出了以下修改版本:
(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属性-甚至还有与父级及其父级的父级事件附件相关的其他属性,如下所示:
答案 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);
}