【问题标题】:How do you log all events fired by an element in jQuery?你如何记录jQuery中一个元素触发的所有事件?
【发布时间】:2011-11-18 08:50:15
【问题描述】:

我想查看用户与其交互时由输入字段触发的所有事件。这包括以下内容:

  1. 点击它。
  2. 点击关闭它。
  3. 进入它。
  4. 远离它。
  5. Ctrl+CCtrl+V 在键盘上。
  6. 右击->粘贴。
  7. 右键单击 -> 剪切。
  8. 右击->复制。
  9. 从另一个应用程序拖放文本。
  10. 用 Javascript 修改它。
  11. 使用调试工具(如 Firebug)对其进行修改。

我想使用console.log 显示它。这在 Javascript/jQuery 中是否可行,如果可以,我该怎么做?

【问题讨论】:

  • 您的问题很有趣,但您在评论中说“我正在寻找的更多是所有被触发事件的列表,所以我知道哪些事件可供我挂钩“——你为什么不问这个? MSDN 的文档非常适合:msdn.microsoft.com/en-us/library/ms533051(v=VS.85).aspx - 并非所有浏览器都支持列出的所有事件,但如果您检查文档中的事件 'on_xyz_',它会告诉您“此事件是在 HTML 4.0 中定义的。”,或“没有适用于此事件的公共标准”,或其他任何内容。

标签: javascript jquery events dom-events


【解决方案1】:

我不知道为什么没有人使用它...(也许因为它只是一个 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

【讨论】:

  • 它不包括自定义事件,但它确实有助于理解事件堆栈。
  • 这是正确答案。你不想在生产代码中使用console.log,可以使用控制台调试事件
  • Googleing monitorEvents 没有提供相关信息,而且我高度怀疑这是非常不标准的
  • @vsync 在引号中尝试“monitorEvents”。它是控制台对象的一部分,但依赖于浏览器。它只是一个调试工具,因为它依赖于控制台......所以标准是无关紧要的
  • 请注意,您也可以使用monitorEvents($0, 'mouse'); 之类的东西来记录inspected(右键单击>“Inspect”)元素的所有事件。 (briangrinstead.com/blog/chrome-developer-tools-monitorevents)
【解决方案2】:
$(element).on("click mousedown mouseup focus blur keydown change",function(e){
     console.log(e);
});

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

【讨论】:

  • 奇怪的是你和肖恩都拼错了function,而且拼写方式一样:)。
  • 看起来这个方法会绑定所有的原生事件。我猜没有办法显示自定义事件,例如如果插件触发了一些自定义事件?
  • 我接受这个作为答案,但我的问题的真正答案是“是与否”。我正在寻找的更多的是所有被触发事件的列表,所以我知道哪些事件可供我挂钩。在这种情况下,我可以看到何时事件被触发,但我必须事先知道它的名称。
  • @Joseph:关于您之前的评论“焦点不是原生事件” - 嗯......是的,它早在 jQuery 之前就已经存在了(就此而言,在 Chrome 和 FF 之前) )。此外,您可能希望将 blur 添加到您的事件列表中。
  • monitorEvents(document) 是真正的答案
【解决方案3】:

有一个很好的通用方式使用 .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 元素并选中“日志事件”。然后每个事件都会记录到控制台(这有时有点烦人,因为它会记录每次鼠标移动......)。

【讨论】:

    【解决方案4】:
    $('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);
    }); 
    

    【讨论】:

      【解决方案5】:

      我知道答案已经被接受,但我认为可能有一种稍微更可靠的方法,您不必事先知道事件的名称。这仅适用于本机事件,但据我所知,不适用于插件创建的自定义事件。我选择省略使用 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);
          });
        });
      

      我希望这对阅读本文的人有所帮助。

      编辑

      所以我看到另一个类似的question here,所以另一个建议是执行以下操作:

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

      【讨论】:

      • 这是最优雅的解决方案。我想不可能发现自定义事件,因为这些事件可以通过 dispatchEvent() 发出。然而,这在一个紧凑、无依赖的代码中涵盖了所有其他内容。
      【解决方案6】:

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

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

      你看到的解释:

      在控制台日志中,您将看到您选择的所有事件(见下文“如何使用”)并显示对象类型、类名、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,感谢您的尝试。因为您没有提供任何示例,所以无法查看问题是在您的代码中还是在我的代码中。因为还有其他人成功地使用了这个例子,所以你可能做错了什么。你检查过你的代码是否有错误吗?
      • 没有错误。我触发了一些事件,但控制台中没有出现日志!我在ubuntu,linux中使用的是最新版本的chrome。
      • @AmirFo:您是否也在 Firefox 中尝试过?什么版本的jQuery?
      • @AmirFo:你是如何触发这些事件的?在触发它之前,您是否将任何事件绑定到 DOM 元素?
      【解决方案7】:

      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
        }
      });
      

      【讨论】:

      • 您能否提供更多有关其工作原理和具体作用的信息?如何将它附加到元素上?
      • 这个脚本修改了HTMLElement.prototype.addEventListener,可能不应该在生产中使用,但它对我的调试有很大帮助。
      • 这不适用于 1 个元素,它适用于所有元素。它接入窗口的事件处理程序并监听发生的一切。它适用于本机事件处理程序和 jQuery。
      【解决方案8】:

      只需将此添加到页面,无需担心,将为您处理休息:

      $('input').live('click mousedown mouseup focus keydown change blur', function(e) {
           console.log(e);
      });
      

      你也可以使用console.log('Input event:' + e.type) 来简化。

      【讨论】:

      • 奇怪的是,你和 Joseph 都拼错了function,而且是一样的:)。
      • 大声笑,嘿...他写了一些,我有进步。 ;)
      • 不要让我评论其他答案,您可以使用 .data("events") 获取事件列表。
      • 它是如何工作的?我试过$('input').data('events'),它返回未定义。
      • 这将返回当前绑定的事件,其中包括自定义事件。如果没有绑定事件,它将返回 undefined。
      【解决方案9】:

      第 1 步:检查 events 上的 HTML element developer console

      第 2 步:收听我们要捕获的 events

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

      祝你好运……

      【讨论】:

        【解决方案10】:
        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 上的开关盒,您只能打印特定事件的信息

        【讨论】:

          【解决方案11】:

          我最近从一个现有的 SO 帖子中找到并修改了这个 sn-p,我无法再次找到它,但我发现它非常有用

          // specify any elements you've attached listeners to here
          const nodes = [document]
          
          // https://developer.mozilla.org/en-US/docs/Web/Events
          const logBrowserEvents = () => {
            const AllEvents = {
              AnimationEvent: ['animationend', 'animationiteration', 'animationstart'],
              AudioProcessingEvent: ['audioprocess'],
              BeforeUnloadEvent: ['beforeunload'],
              CompositionEvent: [
                'compositionend',
                'compositionstart',
                'compositionupdate',
              ],
              ClipboardEvent: ['copy', 'cut', 'paste'],
              DeviceLightEvent: ['devicelight'],
              DeviceMotionEvent: ['devicemotion'],
              DeviceOrientationEvent: ['deviceorientation'],
              DeviceProximityEvent: ['deviceproximity'],
              DragEvent: [
                'drag',
                'dragend',
                'dragenter',
                'dragleave',
                'dragover',
                'dragstart',
                'drop',
              ],
              Event: [
                'DOMContentLoaded',
                'abort',
                'afterprint',
                'beforeprint',
                'cached',
                'canplay',
                'canplaythrough',
                'change',
                'chargingchange',
                'chargingtimechange',
                'checking',
                'close',
                'dischargingtimechange',
                'downloading',
                'durationchange',
                'emptied',
                'ended',
                'error',
                'fullscreenchange',
                'fullscreenerror',
                'input',
                'invalid',
                'languagechange',
                'levelchange',
                'loadeddata',
                'loadedmetadata',
                'noupdate',
                'obsolete',
                'offline',
                'online',
                'open',
                'open',
                'orientationchange',
                'pause',
                'play',
                'playing',
                'pointerlockchange',
                'pointerlockerror',
                'ratechange',
                'readystatechange',
                'reset',
                'seeked',
                'seeking',
                'stalled',
                'submit',
                'success',
                'suspend',
                'timeupdate',
                'updateready',
                'visibilitychange',
                'volumechange',
                'waiting',
              ],
              FocusEvent: [
                'DOMFocusIn',
                'DOMFocusOut',
                'Unimplemented',
                'blur',
                'focus',
                'focusin',
                'focusout',
              ],
              GamepadEvent: ['gamepadconnected', 'gamepaddisconnected'],
              HashChangeEvent: ['hashchange'],
              KeyboardEvent: ['keydown', 'keypress', 'keyup'],
              MessageEvent: ['message'],
              MouseEvent: [
                'click',
                'contextmenu',
                'dblclick',
                'mousedown',
                'mouseenter',
                'mouseleave',
                'mousemove',
                'mouseout',
                'mouseover',
                'mouseup',
                'show',
              ],
              // https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events
              MutationNameEvent: ['DOMAttributeNameChanged', 'DOMElementNameChanged'],
              MutationEvent: [
                'DOMAttrModified',
                'DOMCharacterDataModified',
                'DOMNodeInserted',
                'DOMNodeInsertedIntoDocument',
                'DOMNodeRemoved',
                'DOMNodeRemovedFromDocument',
                'DOMSubtreeModified',
              ],
              OfflineAudioCompletionEvent: ['complete'],
              OtherEvent: ['blocked', 'complete', 'upgradeneeded', 'versionchange'],
              UIEvent: [
                'DOMActivate',
                'abort',
                'error',
                'load',
                'resize',
                'scroll',
                'select',
                'unload',
              ],
              PageTransitionEvent: ['pagehide', 'pageshow'],
              PopStateEvent: ['popstate'],
              ProgressEvent: [
                'abort',
                'error',
                'load',
                'loadend',
                'loadstart',
                'progress',
              ],
              SensorEvent: ['compassneedscalibration', 'Unimplemented', 'userproximity'],
              StorageEvent: ['storage'],
              SVGEvent: [
                'SVGAbort',
                'SVGError',
                'SVGLoad',
                'SVGResize',
                'SVGScroll',
                'SVGUnload',
              ],
              SVGZoomEvent: ['SVGZoom'],
              TimeEvent: ['beginEvent', 'endEvent', 'repeatEvent'],
              TouchEvent: [
                'touchcancel',
                'touchend',
                'touchenter',
                'touchleave',
                'touchmove',
                'touchstart',
              ],
              TransitionEvent: ['transitionend'],
              WheelEvent: ['wheel'],
            }
          
            const RecentlyLoggedDOMEventTypes = {}
          
            Object.keys(AllEvents).forEach((DOMEvent) => {
              const DOMEventTypes = AllEvents[DOMEvent]
          
              if (Object.prototype.hasOwnProperty.call(AllEvents, DOMEvent)) {
                DOMEventTypes.forEach((DOMEventType) => {
                  const DOMEventCategory = `${DOMEvent} ${DOMEventType}`
          
                  nodes.forEach((node) => {
                    node.addEventListener(
                      DOMEventType,
                      (e) => {
                        if (RecentlyLoggedDOMEventTypes[DOMEventCategory]) return
          
                        RecentlyLoggedDOMEventTypes[DOMEventCategory] = true
          
                        // NOTE: throttle continuous events
                        setTimeout(() => {
                          RecentlyLoggedDOMEventTypes[DOMEventCategory] = false
                        }, 1000)
          
                        const isActive = e.target === document.activeElement
          
                        // https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
                        const hasActiveElement = document.activeElement !== document.body
          
                        const msg = [
                          DOMEventCategory,
                          'target:',
                          e.target,
                          ...(hasActiveElement
                            ? ['active:', document.activeElement]
                            : []),
                        ]
          
                        if (isActive) {
                          console.info(...msg)
                        }
                      },
                      true,
                    )
                  })
                })
              }
            })
          }
          logBrowserEvents()
          // export default logBrowserEvents
          

          【讨论】:

            【解决方案12】:

            这是一种非 jquery 方法,可以使用您的代码在控制台中监视事件,而无需使用 monitorEvents(),因为这只适用于 Chrome 开发者控制台。您还可以通过编辑 no_watch 数组来选择不监视某些事件。

                function getEvents(obj) {
                window["events_list"] = [];
                var no_watch = ['mouse', 'pointer']; // Array of event types not to watch
                var no_watch_reg = new RegExp(no_watch.join("|"));
            
                for (var prop in obj) {
                    if (prop.indexOf("on") === 0) {
                        prop = prop.substring(2); // remove "on" from beginning
                        if (!prop.match(no_watch_reg)) {
                            window["events_list"].push(prop);
                            window.addEventListener(prop, function() {
                                console.log(this.event); // Display fired event in console
                            } , false);
                        }
                    }
                }
                window["events_list"].sort(); // Alphabetical order 
            
            }
            
            getEvents(document); // Put window, document or any html element here
            console.log(events_list); // List every event on element
            

            【讨论】:

              【解决方案13】:

              如何监听 Element (Vanilla JS) 上的所有事件


              对于所有本机事件,我们可以通过遍历 target.onevent 属性并为所有事件安装我们的侦听器来检索支持的事件列表。

              for (const key in target) {
                  if(/^on/.test(key)) {
                      const eventType = key.substr(2);
                      target.addEventListener(eventType, listener);
                  }
              }
              

              据我所知,发出事件的唯一另一种方式是通过EventTarget.dispatchEvent,每个Node 和因此每个Element 都继承。
              要监听所有这些手动触发的事件,我们可以全局代理dispatchEvent 方法,并为我们刚刚看到的名称的事件安装我们的监听器✨ ^^

              const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
              EventTarget.prototype.dispatchEvent = function (event) {
                  if (!alreadyListenedEventTypes.has(event.type)) {
                      target.addEventListener(event.type, listener, ...otherArguments);
                      alreadyListenedEventTypes.add(event.type);
                  }
                  dispatchEvent_original.apply(this, arguments);
              };
              

              ? 函数 sn-p ?

              function addEventListenerAll(target, listener, ...otherArguments) {
              
                  // install listeners for all natively triggered events
                  for (const key in target) {
                      if (/^on/.test(key)) {
                          const eventType = key.substr(2);
                          target.addEventListener(eventType, listener, ...otherArguments);
                      }
                  }
              
                  // dynamically install listeners for all manually triggered events, just-in-time before they're dispatched ;D
                  const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
                  function dispatchEvent(event) {
                      target.addEventListener(event.type, listener, ...otherArguments);  // multiple identical listeners are automatically discarded
                      dispatchEvent_original.apply(this, arguments);
                  }
                  EventTarget.prototype.dispatchEvent = dispatchEvent;
                  if (EventTarget.prototype.dispatchEvent !== dispatchEvent) throw new Error(`Browser is smarter than you think!`);
              
              }
              
              
              // usage example
              const input = document.querySelector('input');
              addEventListenerAll(input, (evt) => {
                  console.log(evt.type);
              });
              input.focus();
              input.click();
              input.dispatchEvent(new Event('omg!', { bubbles: true }));
              
              
              // usage example with `useCapture`
              // (also receives `bubbles: false` events, but in reverse order)
              addEventListenerAll(
                  input,
                  (evt) => { console.log(evt.type); },
                  true
              );
              document.body.dispatchEvent(new Event('omfggg!', { bubbles: false }));
              

              【讨论】:

                猜你喜欢
                • 2010-10-30
                • 2012-01-23
                • 2012-10-30
                • 1970-01-01
                • 2020-10-23
                • 2015-04-22
                • 1970-01-01
                • 2017-11-03
                • 1970-01-01
                相关资源
                最近更新 更多