简体   繁体   English

如何使用 JavaScript 查找所有具有事件侦听器的元素?

[英]How to use JavaScript to find all elements which have event listeners?

<div id="test1" onlick="testFunction()" role="button" tabindex="0">A custom button</div>

<div id="test2" role="button" tabindex="0">Another custom button</div>

<button class="test3">A final button</button>

<ul id="test4">
  <li>Cookies</li>
  <li>Cream</li>
</ul>

<div id="test5">Just a div, not clickable </div>
document.getElementById('test2').addEventListener('keypress', function() { 
    console.log("foo");
  }
)
document.querySelectorAll('.test3').forEach(item => {
    item.addEventListener('click', event => {
      console.log("bar");
    })
  })

document.getElementById('test4').onclick = function(event) {
  let target = event.target;

  if (target.tagName != 'li') {
     event.target.addClass('highlight');
  }
};

I'm interested in using JavaScript (preferably no jQuery or other library) to find all DOM elements which have events attached to them.我对使用 JavaScript(最好没有 jQuery 或其他库)来查找所有附加了事件的 DOM 元素很感兴趣。 There are many ways to find elements that have HTML event attributes like #test1 .有很多方法可以找到具有 HTML 事件属性的元素,例如#test1 But it is unclear how to find elements that have events added via a script like #test2 or .test3 or the <ul id="test4"> .但目前尚不清楚如何找到通过#test2.test3<ul id="test4">等脚本添加事件的元素。 A correct answer would return an array with four elements.正确答案将返回一个包含四个元素的数组。

An even better response would additionally find the elements using event delegation like the <li> but it seems like that may not be possible.更好的响应会另外找到使用事件委托的元素,如<li>但看起来这可能是不可能的。

EDIT: querySelectorAll() now selects the test3 class instead of test3 tag编辑:querySelectorAll() 现在选择 test3 类而不是 test3 标签

There is no native javascript api that allows you to find event listeners that were added using eventTarget.addEventListener .没有本机 javascript api 允许您查找使用eventTarget.addEventListener添加的事件侦听器。

You can still get events added using the onclick attribute whether the attribute was set using javascript or inline through html - in this case u are not getting the event listener, but you are getting the value of the onclick attribute which are two different things. You can still get events added using the onclick attribute whether the attribute was set using javascript or inline through html - in this case u are not getting the event listener, but you are getting the value of the onclick attribute which are two different things.

Javascript offers no api for doing so, because dom elements can be removed while event listeners still referencing them. Javascript 不提供 api 这样做,因为可以在事件侦听器仍然引用它们时删除 dom 元素。

If you want to keep track of event listeners attached to dom elements you have to do that yourself.如果你想跟踪附加到 dom 元素的事件监听器,你必须自己做。

Apart from that chrome has getEventListeners command line api which works with dom elements, however it is a developer tools command line api and so it only works when called from developer tools.除此之外,chrome 还有getEventListeners命令行 api 可与 dom 元素一起使用,但它是开发人员工具命令行 api ,因此仅在从开发人员工具调用时才有效。

There is no way, to do so directly with JavaScript.没办法,直接用JavaScript来做。

However, you can use this approach and add an attribute while binding events to the elements.但是,您可以使用这种方法并在将事件绑定到元素时添加属性。

 document.getElementById('test2').addEventListener('keypress', function() { this.setAttribute("event", "yes"); console.log("foo"); } ) document.querySelectorAll('test3').forEach(item => { item.addEventListener('click', event => { this.setAttribute("event", "yes"); console.log("bar"); }) }) document.getElementById('test4').onclick = function(event) { let target = event.target; this.setAttribute("event", "yes"); if (target.tagName.= 'li') { event.target;addClass('highlight'); } };

And this is how you can find the elements having events bind to them:这就是您如何找到具有事件绑定到它们的元素的方法:

 var eventElements = document.querySelectorAll("[event='yes']"); var countEventElements = eventElements.length;

You can extend EventTarget.addEventListener so that any element to which you add an EventListener then declares that EventListener in an HTML5 custom data-* attribute in its own markup.您可以扩展EventTarget.addEventListener ,这样您添加EventListener任何元素都可以在其自己的标记中的HTML5 自定义 data-* 属性中声明该EventListener

When declared, the custom attribute will look like this:声明后,自定义属性将如下所示:

data-eventlisteners="['mouseover:showButton','mouseout:fadeButton','click:animateButton']"

Once one or more elements have such custom attributes , you may query the elements via JavaScript.一旦一个或多个元素具有此类自定义属性,您就可以通过 JavaScript 查询这些元素。

eg例如

  1. document.querySelectorAll('[data-eventlisteners]') will reveal which elements on the page have EventListeners attached document.querySelectorAll('[data-eventlisteners]')将显示页面上的哪些元素附加了EventListeners

  2. document.querySelectorAll('[data-eventlisteners*=","]') will reveal which elements on the page have more than one EventListener attached document.querySelectorAll('[data-eventlisteners*=","]')将显示页面上的哪些元素附加了多个EventListener

  3. document.querySelectorAll('[data-eventlisteners*="mouseover:"]') will reveal which elements on the page have a mouseover EventListener attached document.querySelectorAll('[data-eventlisteners*="mouseover:"]')将显示页面上的哪些元素附加了mouseover EventListener

  4. document.querySelectorAll('[data-eventlisteners*="click:"][data-eventlisteners*="mouseout:"]') will reveal which elements on the page have both a click and a mouseout EventListener attached document.querySelectorAll('[data-eventlisteners*="click:"][data-eventlisteners*="mouseout:"]')将揭示页面上的哪些元素同时具有clickmouseout EventListener

etc.等等


Working Example:工作示例:

 const declareEventListeners = () => { EventTarget.prototype._addEventListener = EventTarget.prototype.addEventListener; EventTarget.prototype.addEventListener = function(eventType, eventFunction, eventOptions) { // REINSTATE ORIGINAL FUNCTIONALITY FOR addEventListener() METHOD let _eventOptions = (eventOptions === undefined)? false: eventOptions; this._addEventListener(eventType, eventFunction, _eventOptions); // THEN, IF EVENTTARGET IS NOT WINDOW OR DOCUMENT if (this.nodeType === 1) { let eventAction = eventFunction.name || 'anonymousFunction'; let eventListenerLabel = `${eventType}:${eventAction}`; let eventListenerLabelsArray = (this.dataset.eventlisteners)? JSON.parse(this.dataset.eventlisteners.replaceAll( "'", '"')): []; eventListenerLabelsArray.push(eventListenerLabel); let eventListenerLabelsString = JSON.stringify(eventListenerLabelsArray).replaceAll('"', "'"); this.dataset.eventlisteners = eventListenerLabelsString; } } }; const clickMe = (e) => { e.target.classList.toggle('circle'); } const mouseoverMe = (e) => { e.target.style.setProperty('background-color', 'rgb(255, 127, 0)'); } const mouseoutMe = (e) => { e.target.removeAttribute('style'); } const logMarkup = () => { console.log(document.querySelector('section').innerHTML); } declareEventListeners(); document.querySelector('.div1').addEventListener('click', clickMe, false); document.querySelector('.div2').addEventListener('mouseover', mouseoverMe, false); document.querySelector('.div2').addEventListener('mouseout', mouseoutMe, false); logMarkup();
 .div1, .div2 { float: left; width: 100px; height: 100px; line-height: 50px; margin-right: 12px; text-align: center; color: rgb(255, 255, 255); background-color: rgb(255, 0, 0); }.div1 { line-height: 100px; cursor: pointer; }.div1.circle { border-radius: 50%; }
 <section> <div class="div1">click</div> <div class="div2">mouseover<br />mouseout</div> </section>

You'll see in the example above:您将在上面的示例中看到:

  • .div1 reveals itself as having a single EventListener which listens for click and fires the function clickMe() .div1显示自己有一个EventListener ,它监听click并触发函数clickMe()

  • .div2 reveals itself as having two EventListeners which listen for mouseover and mouseout , which, respectively, fire the functions mouseoverMe() and mouseoutMe() .div2显示自己有两个EventListeners ,它们监听mouseovermouseout ,分别触发函数mouseoverMe()mouseoutMe()


NB I've modified the script above quite a lot but it was originally inspired by:注意我已经对上面的脚本进行了很多修改,但它最初的灵感来自:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM