如何使用Firebug或类似工具调试JavaScript / jQuery事件绑定?

618

我需要调试一个使用jQuery进行相当复杂和混乱DOM操作的web应用程序。在某个时刻,绑定到特定元素的一些事件不起作用。

如果我有编辑应用程序源代码的能力,我会深入挖掘并添加大量Firebugconsole.log()语句,并注释/取消代码段以尝试准确定位问题所在。但假设我无法编辑应用程序代码,需要完全在Firefox中使用Firebug或类似工具进行工作。

Firebug非常擅长让我浏览和操作DOM。迄今为止,我还没有找到如何使用Firebug进行事件调试的方法。具体来说,我只想在给定时间内看到绑定到特定元素的事件处理程序列表(使用Firebug JavaScript断点跟踪更改)。但是Firebug要么没有查看绑定事件的功能,要么我太傻了找不到它。:-)

有什么建议或想法吗?理想情况下,我希望只需查看并编辑绑定到元素的事件,就像我今天可以编辑DOM一样。

15个回答

356

请查看如何在DOM节点上查找事件监听器

简而言之,假设某个时刻已将事件处理程序附加到您的元素(例如):$('#foo').click(function() { console.log('clicked!') });

您可以像这样检查它:

  • jQuery 1.3.x

    var clickEvents = $('#foo').data("events").click;
    jQuery.each(clickEvents, function(key, value) {
      console.log(value) // prints "function() { console.log('clicked!') }"
    })
    
  • jQuery 1.4.x

    var clickEvents = $('#foo').data("events").click;
    jQuery.each(clickEvents, function(key, handlerObj) {
      console.log(handlerObj.handler) // prints "function() { console.log('clicked!') }"
    })
    

请查看jQuery.fn.data(这是jQuery内部存储处理程序的位置)。

  • jQuery 1.8.x

    var clickEvents = $._data($('#foo')[0], "events").click;
    jQuery.each(clickEvents, function(key, handlerObj) {
      console.log(handlerObj.handler) // prints "function() { console.log('clicked!') }"
    })
    

21
请注意:这不会显示未附加jQuery的事件。 - Ruan Mendes
10
完全同意关于console.log()的观点,不过应该添加类似于if (window.console)这样的条件判断语句,以防止它被遗留在代码中(这比使用alert()容易出错),导致IE浏览器崩溃。 - thepeer
14
个人而言,我更喜欢在文件开头检查控制台,如果不存在则创建一个虚假对象。 - Andrew
3
@BrainSlugs83:请参考此回答中的链接(简而言之,您无法这样做)。 - Crescent Fresh
console.debug() 会在调试控制台中输出信息。 - Eli
显示剩余3条评论

162
有一个很好用的书签脚本叫做Visual Event,可以显示元素上所有的事件。不同类型的事件(鼠标、键盘等)有着着色的高亮标记。当你悬停在它们上面时,它会显示事件处理程序的正文内容、它是如何附加的以及文件/行号 (在 WebKit 和 Opera 中)。你也可以手动触发事件。

它不能找到每一个事件,因为没有标准的方法来查找附加到一个元素上的事件处理程序,但它能够与流行的库一起使用,如 jQuery、Prototype、MooTools、YUI 等。


8
请注意,由于此代码运行在内容 JavaScript 中,因此它通过查询 JavaScript 库来获取其数据。因此,它只会显示使用受支持的库(包括 jQuery)添加的事件。 - Matthew Flaschen

41
你可以使用FireQuery来查看Firebug的HTML标签页中附加到DOM元素的任何事件,并显示通过$.data附加到元素的任何数据。

1
那个插件有一个非常大的缺点:当你在调试时,想要检查包含jQuery集合的变量的值时,当你的代码暂停时,你无法检查该值。这在Firebug中并不是问题。这是我卸载它的原因。 - Maarten Kieft
1
FireQuery似乎不再显示附加的事件了 :( - Matty J

25

这里有一个插件可以列出给定元素/事件的所有事件处理程序:

$.fn.listHandlers = function(events, outputFunction) {
    return this.each(function(i){
        var elem = this,
            dEvents = $(this).data('events');
        if (!dEvents) {return;}
        $.each(dEvents, function(name, handler){
            if((new RegExp('^(' + (events === '*' ? '.+' : events.replace(',','|').replace(/^on/i,'')) + ')$' ,'i')).test(name)) {
               $.each(handler, function(i,handler){
                   outputFunction(elem, '\n' + i + ': [' + name + '] : ' + handler );
               });
           }
        });
    });
};

像这样使用:

// List all onclick handlers of all anchor elements:
$('a').listHandlers('onclick', console.info);

// List all handlers for all events of all elements:
$('*').listHandlers('*', console.info);

// Write a custom output function:
$('#whatever').listHandlers('click',function(element,data){
    $('body').prepend('<br />' + element.nodeName + ': <br /><pre>' + data + '<\/pre>');
});

来源:(我的博客) -> http://james.padolsey.com/javascript/debug-jquery-events-with-listhandlers/


23

2
而对于Firefox,说明在MDN上。 - Fla

11

在jQuery 1.7+中使用 $._data(htmlElement, "events")

例如:

$._data(document, "events")$._data($('.class_name').get(0), "events")


8

正如同事所建议的,console.log > alert:

var clickEvents = $('#foo').data("events").click;
jQuery.each(clickEvents, function(key, value) {
    console.log(value);
})

6

jQuery将事件存储在以下位置:

$("a#somefoo").data("events")

执行console.log($("a#somefoo").data("events"))会列出已附加到该元素的事件。


5

在最新的Chrome(v29)中使用DevTools调试事件时,我发现以下两个提示非常有用:

  1. 列出最后选择的DOM元素的jQuery事件

    • 检查页面上的元素
    • 在控制台中输入以下内容:

    $._data($0, "events") //假设使用的是jQuery 1.7+

  2. 它将列出与之关联的所有jQuery事件对象,展开感兴趣的事件,在“handler”属性的函数上右键单击并选择“显示函数定义”。它将打开包含指定函数的文件。
  3. 利用monitorEvents()命令


5

ev图标显示元素的事件

在Firefox开发者工具的检查器面板中,列出了绑定在元素上的所有事件。

首先使用Ctrl + Shift + C选择一个元素,例如Stack Overflow的赞同箭头。

点击元素右侧的ev图标,会弹出一个对话框:

事件提示

单击所需事件的暂停符号||,这将在处理程序的行上打开调试器。

现在,您可以像通常在调试器中一样,在该行的左边缘单击以在那里设置断点。

有关详细信息,请参见:https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_event_listeners

不幸的是,我找不到使其与代码美化良好配合的方法,它似乎只是在被压缩的行处打开:如何在Firefox / Firebug中美化JavaScript和CSS?

已在Firefox 42上测试。


不幸的是,这对于定位继承的监听器并不起作用。 - chukko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接