如何使用jQuery记录元素触发的所有事件?

112
我想看到用户与输入框交互时触发的所有事件,包括以下内容:
  1. 单击它。
  2. 从它上面单击出去。
  3. 通过 Tab 键进入它。
  4. 通过 Tab 键离开它。
  5. 在键盘上使用 Ctrl+CCtrl+V
  6. 右键单击-> 粘贴。
  7. 右键单击-> 剪切。
  8. 右键单击-> 复制。
  9. 从另一个应用程序拖放文本。
  10. 使用Javascript修改。
  11. 使用Firebug等调试工具进行修改。
我希望使用console.log来显示它。这在JavaScript / jQuery中是否可能,如果是,我该怎么做?

您的问题本身很有趣,但是您在评论中说,“我想要的更多是所有正在触发的事件列表,这样我就知道可以连接哪些事件”,那为什么您不直接问呢?MSDN的文档对此非常好:http://msdn.microsoft.com/en-us/library/ms533051(v=VS.85).aspx - 并非所有列出的事件都受到所有浏览器的支持,但如果您检查'on_xyz_'事件的文档,它会告诉您“此事件定义在HTML 4.0中”,或者“没有适用于此事件的公共标准”,或其他内容。 - nnnnnn
3
这是一篇关于如何使用jQuery记录元素触发事件的答案。简要概括起来,你需要使用jQuery的on()方法来绑定事件,并在回调函数中记录事件名称和任何相关数据。你可以将日志输出到控制台或发送到服务器以进行后续分析。以下是示例代码:$('your-element').on('click', function(event) { console.log('Event name: ' + event.type); console.log('Event data: ', event.data); // 发送日志到服务器的代码(可选) }); - neaumusic
14个回答

255

我不知道为什么没有人使用这个...(也许是因为它只是 WebKit 的东西)

打开控制台:

monitorEvents(document.body); // logs all events on the body

monitorEvents(document.body, 'mouse'); // logs mouse events on the body

monitorEvents(document.body.querySelectorAll('input')); // logs all events on inputs

8
它不能覆盖自定义事件,但它确实有助于理解事件堆栈。 - sidonaldson
2
谷歌搜索“monitorEvents”没有相关信息,而且我非常怀疑这是非常不标准的。 - vsync
5
请尝试在引号中使用 "monitorEvents"。它是控制台对象的一部分,但取决于浏览器。它只是一个调试工具,因为它依赖于控制台... 所以它的标准性不重要。 - sidonaldson
3
请注意,您还可以使用类似于 monitorEvents($0, 'mouse'); 的内容来记录检查过的元素的所有事件(右键单击>“检查”)。 (http://www.briangrinstead.com/blog/chrome-developer-tools-monitorevents) - rinogo
1
这是源代码:https://chromium.googlesource.com/chromium/blink/+/master/Source/core/inspector/InjectedScriptSource.js#1785 - mbomb007
显示剩余4条评论

76
$(element).on("click mousedown mouseup focus blur keydown change",function(e){
     console.log(e);
});

这将为您提供许多(但不是全部)关于事件是否被触发的信息......除非像这样手动编码,我想不出其他任何方法来做到这一点。


1
看起来这个方法将绑定所有本地事件。我猜想没有办法显示自定义事件,例如如果插件触发了一些自定义事件? - Daniel T.
@Daniel T. 哈哈哈哈 XD 看来我们有点复制/粘贴的问题 :P - Joseph Marikle
2
我接受这个答案,但对于我的问题来说,真正的答案是“是和不是”。我想要的更多是一个列出所有被触发事件的列表,这样我就知道哪些事件可以供我挂钩。在这种情况下,我可以看到事件何时被触发,但我必须事先知道它的名称。 - Daniel T.
4
@Joseph: 关于您早前的评论“focus不是本地事件” - 嗯...它确实是一个早在jQuery(以及Chrome和FF之前)存在已久的本地事件。此外,您可能需要将blur添加到您的事件列表中。 - nnnnnn
3
monitorEvents(document) 是真正的答案。 - neaumusic
显示剩余7条评论

33

有一种很好的通用方法是使用`.data('events')`集合:

function getEventsList($obj) {
    var ev = new Array(),
        events = $obj.data('events'),
        i;
    for(i in events) { ev.push(i); }
    return ev.join(' ');
}

$obj.on(getEventsList($obj), function(e) {
    console.log(e);
});

这将记录jQuery已绑定到元素的每个事件,以及在此特定事件触发时的状态。这段代码对我非常有帮助。

顺便说一句:如果您想查看对象上触发的所有可能事件,请使用firebug:只需右键单击HTML选项卡中的DOM元素并选中“Log Events”。然后每个事件都会被记录到控制台中(有时会有点烦人,因为它会记录每个鼠标移动...)。


20
$('body').on("click mousedown mouseup focus blur keydown change mouseup click dblclick mousemove mouseover mouseout mousewheel keydown keyup keypress textInput touchstart touchmove touchend touchcancel resize scroll zoom focus blur select change submit reset",function(e){
     console.log(e);
}); 

14

我知道这个问题的答案已经被接受了,但我认为可能有一种稍微更可靠的方法,您不一定需要事先知道事件的名称。据我所知,这仅适用于本机事件,而不是由插件创建的自定义事件。为简化事情,我选择省略使用jQuery。

let input = document.getElementById('inputId');

Object.getOwnPropertyNames(input)
  .filter(key => key.slice(0, 2) === 'on')
  .map(key => key.slice(2))
  .forEach(eventName => {
    input.addEventListener(eventName, event => {
      console.log(event.type);
      console.log(event);
    });
  });

我希望这篇文章能帮到任何阅读它的人。

编辑

我在 这里 看到了另一个类似的问题,那么另一个建议是这样做:

monitorEvents(document.getElementById('inputId'));

这是一组解决方案中最优雅的一个。我想发现自定义事件可能是不可能的,因为它们可以通过dispatchEvent()来发出。然而,这段代码紧凑、无依赖性,覆盖了其他所有内容。 - Yogi

12

老帖子,我知道。我也需要一些东西来监视事件,并编写了这个非常方便(优秀)的解决方案。你可以使用这个钩子(在Windows编程中称为钩子)监视所有事件。此钩子不会影响您软件/程序的操作。

控制台日志中,您可以看到类似以下内容:

console log

所看到的内容解释如下:

在控制台日志中,您将看到您选择的所有事件(请参见下面的"如何使用"),并显示对象类型、类名(s)、id、<:函数名称>、<:事件名称>。对象的格式与CSS类似。

当您单击按钮或任何绑定事件时,您将在控制台日志中看到它。

我编写的代码:

function setJQueryEventHandlersDebugHooks(bMonTrigger, bMonOn, bMonOff)
{
   jQuery.fn.___getHookName___ = function()    
       {
          // First, get object name
         var sName = new String( this[0].constructor ),
         i = sName.indexOf(' ');
         sName = sName.substr( i, sName.indexOf('(')-i );    

         // Classname can be more than one, add class points to all
         if( typeof this[0].className === 'string' )
         {
           var sClasses = this[0].className.split(' ');
           sClasses[0]='.'+sClasses[0];
           sClasses = sClasses.join('.');
           sName+=sClasses;
         }
         // Get id if there is one
         sName+=(this[0].id)?('#'+this[0].id):'';
         return sName;
       };

   var bTrigger        = (typeof bMonTrigger !== "undefined")?bMonTrigger:true,
       bOn             = (typeof bMonOn !== "undefined")?bMonOn:true,
       bOff            = (typeof bMonOff !== "undefined")?bMonOff:true,
       fTriggerInherited = jQuery.fn.trigger,
       fOnInherited    = jQuery.fn.on,
       fOffInherited   = jQuery.fn.off;

   if( bTrigger )
   {
    jQuery.fn.trigger = function()
    {
     console.log( this.___getHookName___()+':trigger('+arguments[0]+')' );
     return fTriggerInherited.apply(this,arguments);
    };
   }

   if( bOn )
   {
    jQuery.fn.on = function()
    {
     if( !this[0].__hooked__ ) 
     {
       this[0].__hooked__ = true; // avoids infinite loop!
       console.log( this.___getHookName___()+':on('+arguments[0]+') - binded' );
       $(this).on( arguments[0], function(e)
       {
         console.log( $(this).___getHookName___()+':'+e.type );
       });
     }
     var uResult = fOnInherited.apply(this,arguments);
     this[0].__hooked__ = false; // reset for another event
     return uResult;
    };
   }

   if( bOff )
   {
    jQuery.fn.off = function()
    {
     if( !this[0].__unhooked__ ) 
     {
       this[0].__unhooked__ = true; // avoids infinite loop!
       console.log( this.___getHookName___()+':off('+arguments[0]+') - unbinded' );
       $(this).off( arguments[0] );
     }

     var uResult = fOffInherited.apply(this,arguments);
     this[0].__unhooked__ = false; // reset for another event
     return uResult;
    };
   }
}

如何使用:

监控所有事件:

setJQueryEventHandlersDebugHooks();

仅监控所有触发器:

setJQueryEventHandlersDebugHooks(true,false,false);

仅监视所有“ON”事件:

setJQueryEventHandlersDebugHooks(false,true,false);

仅监视所有OFF解绑:

setJQueryEventHandlersDebugHooks(false,false,true);

备注/注意事项:

  • 仅用于调试,最终产品版本中使用时请关闭
  • 如果你想查看所有事件,必须在加载jQuery后直接调用此函数
  • 如果您只想查看较少的事件,则可以在需要时调用该函数
  • 如果您想自动执行它,请在函数周围放置();

希望对您有所帮助! ;-)


嗨@AmirFo,感谢您的尝试。由于您没有提供任何示例,因此无法确定问题是在您的代码还是我的代码中。因为其他人已经成功使用了这个示例,所以有可能是您做错了什么。您是否检查过自己的代码是否有错误? - Codebeat
没有错误。我触发了一些事件,但控制台中没有日志出现!我在Ubuntu Linux中使用最新版本的Chrome。 - Amir Fo
@AmirFo:你也在Firefox中尝试过吗?jQuery的哪个版本? - Codebeat
@AmirFo:您是如何触发事件的?在触发之前,是否将任何事件绑定到DOM元素上? - Codebeat

4

https://github.com/robertleeplummerjr/wiretap.js

new Wiretap({
  add: function() {
      //fire when an event is bound to element
  },
  before: function() {
      //fire just before an event executes, arguments are automatic
  },
  after: function() {
      //fire just after an event executes, arguments are automatic
  }
});

1
你能提供更多关于它如何工作以及具体做什么的信息吗?我该如何将它附加到一个元素上? - Josiah
这个脚本修改了HTMLElement.prototype.addEventListener,可能不适合用于生产环境,但是对于调试目的它已经帮了我很大的忙。 - Günter Zöchbauer
1
这不仅适用于一个元素,而是适用于所有元素。它会连接到窗口的事件处理程序并监听发生的所有事情。它可以与本地事件处理程序和jQuery一起使用。 - Robert Plummer

2

步骤1:在开发者控制台中检查HTML元素事件

enter image description here

步骤2:监听我们想要捕获的事件

$(document).on('ch-ui-container-closed ch-ui-container-opened', function(evt){
 console.log(evt);
});

祝你好运...


2
只需将此内容添加到页面中,其他事情无需担心,它会为您处理剩下的部分。
$('input').live('click mousedown mouseup focus keydown change blur', function(e) {
     console.log(e);
});

您可以使用 console.log('Input event:' + e.type) 来使其更加易于理解。

3
有趣的是,你和 Joseph 都拼错了 function 这个单词,而且错法一模一样 :)。 - Daniel T.
嘿...他写了一些,我有个改进点。;) - Shawn Khameneh
1
无法评论其他答案,您可以使用.data(“events”)来获取事件列表。 - Shawn Khameneh
它是如何工作的?我尝试了 $('input').data('events'),但它返回未定义。 - Daniel T.
这将返回当前绑定的事件,包括自定义事件。如果没有绑定事件,则将返回未定义。 - Shawn Khameneh

2
function bindAllEvents (el) {
  for (const key in el) {
      if (key.slice(0, 2) === 'on') {
          el.addEventListener(key.slice(2), e => console.log(e.type));
      }
  }
}
bindAllEvents($('.yourElement'))

这段代码使用了一些ES6语法来使其更美观,但也可以轻松地转换为适用于旧版浏览器的语法。在与事件监听器相关联的函数中,目前只记录了发生了哪种类型的事件,但您可以在此处打印出其他信息,或者使用e.type的switch case仅打印特定事件的信息。


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