Javascript 如何检查动态附加的事件侦听器是否存在?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11455515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check whether dynamically attached event listener exists or not?
提问by Stano
Here is my problem: is it possible somehow to check for existence of dynamically attached event listener? Or how can I check the status of the "onclick" (?) property in DOM? I have searched internet just like Stack Overflow for a solution, but no luck. Here is my html:
这是我的问题:是否有可能以某种方式检查动态附加事件侦听器的存在?或者如何检查 DOM 中“onclick”(?) 属性的状态?我已经像 Stack Overflow 一样在互联网上搜索了解决方案,但没有运气。这是我的 html:
<a id="link1" onclick="linkclick(event)"> link 1 </a>
<a id="link2"> link 2 </a> <!-- without inline onclick handler -->
Then in Javascript I attach dynamically created event listener to the 2nd link:
然后在 Javascript 中,我将动态创建的事件侦听器附加到第二个链接:
document.getElementById('link2').addEventListener('click', linkclick, false);
The code runs well, but all my attempts to detect that attached listener fail:
代码运行良好,但我所有检测附加侦听器的尝试都失败了:
// test for #link2 - dynamically created eventlistener
alert(elem.onclick); // null
alert(elem.hasAttribute('onclick')); // false
alert(elem.click); // function click(){[native code]} // btw, what's this?
jsFiddle is here. If you click "Add onclick for 2" and then "[link 2]", event fires well, but the "Test link 2" always reports false. Can somebody help?
jsFiddle 在这里。如果您单击“为 2 添加 onclick”,然后单击“[链接 2]”,则事件触发良好,但“测试链接 2”始终报告错误。有人可以帮忙吗?
采纳答案by Ivan
There is no way to check whether dynamically attached event listeners exist or not.
没有办法检查动态附加的事件侦听器是否存在。
The only way you can see if an event listener is attached is by attaching event listeners like this:
查看是否附加了事件侦听器的唯一方法是像这样附加事件侦听器:
elem.onclick = function () { console.log (1) }
You can then test if an event listener was attached to onclick
by returning !!elem.onclick
(or something similar).
然后,您可以onclick
通过返回!!elem.onclick
(或类似的东西)来测试是否附加了事件侦听器。
回答by Karol Grabowski
I did something like that:
我做了这样的事情:
const element = document.getElementById('div');
if (element.getAttribute('listener') !== 'true') {
element.addEventListener('click', function (e) {
const elementClicked = e.target;
elementClicked.setAttribute('listener', 'true');
console.log('event has been attached');
});
}
Creating special attribute for an element when listener is attached and then checking if it exist.
附加侦听器时为元素创建特殊属性,然后检查它是否存在。
回答by Cesar
What I would do is create a Boolean outside your function that starts out as FALSE and gets set to TRUE when you attach the event. This would serve as some sort of flag for you before you attach the event again. Here's an example of the idea.
我会做的是在您的函数之外创建一个布尔值,该布尔值以 FALSE 开始,并在您附加事件时设置为 TRUE。在您再次附加事件之前,这将为您提供某种标志。这是这个想法的一个例子。
// initial load
var attached = false;
// this will only execute code once
doSomething = function()
{
if (!attached)
{
attached = true;
//code
}
}
//attach your function with change event
window.onload = function()
{
var txtbox = document.getElementById('textboxID');
if (window.addEventListener)
{
txtbox.addEventListener('change', doSomething, false);
}
else if(window.attachEvent)
{
txtbox.attachEvent('onchange', doSomething);
}
}
回答by arufian
Possible duplicate: Check if an element has event listener on it. No jQueryPlease find my answer there.
可能的重复:检查元素上是否有事件侦听器。没有 jQuery请在那里找到我的答案。
Basically here is the trick for Chromium (Chrome) browser:
基本上这里是 Chromium (Chrome) 浏览器的技巧:
getEventListeners(document.querySelector('your-element-selector'));
回答by Angel Politis
tl;dr: No, you cannot do this in any natively supported way.
tl;dr:不,您不能以任何本机支持的方式执行此操作。
The only way I know to achieve this would be to create a custom storage object where you keep a record of the listeners added. Something along the following lines:
我知道实现这一目标的唯一方法是创建一个自定义存储对象,您可以在其中记录添加的侦听器。大致如下:
/* Create a storage object. */
var CustomEventStorage = [];
Step 1:First, you will need a function that can traverse the storage object and return the record of an element given the element (or false).
第 1 步:首先,您需要一个可以遍历存储对象并返回给定元素(或 false)的元素记录的函数。
/* The function that finds a record in the storage by a given element. */
function findRecordByElement (element) {
/* Iterate over every entry in the storage object. */
for (var index = 0, length = CustomEventStorage.length; index < length; index++) {
/* Cache the record. */
var record = CustomEventStorage[index];
/* Check whether the given element exists. */
if (element == record.element) {
/* Return the record. */
return record;
}
}
/* Return false by default. */
return false;
}
Step 2:Then, you will need a function that can add an event listener but also insert the listener to the storage object.
第 2 步:然后,您将需要一个可以添加事件侦听器但也可以将侦听器插入存储对象的函数。
/* The function that adds an event listener, while storing it in the storage object. */
function insertListener (element, event, listener, options) {
/* Use the element given to retrieve the record. */
var record = findRecordByElement(element);
/* Check whether any record was found. */
if (record) {
/* Normalise the event of the listeners object, in case it doesn't exist. */
record.listeners[event] = record.listeners[event] || [];
}
else {
/* Create an object to insert into the storage object. */
record = {
element: element,
listeners: {}
};
/* Create an array for event in the record. */
record.listeners[event] = [];
/* Insert the record in the storage. */
CustomEventStorage.push(record);
}
/* Insert the listener to the event array. */
record.listeners[event].push(listener);
/* Add the event listener to the element. */
element.addEventListener(event, listener, options);
}
Step 3:As regards the actual requirement of your question, you will need the following function to check whether an element has been added an event listener for a specified event.
步骤3:根据您的问题的实际需求,您将需要以下函数来检查元素是否已添加指定事件的事件侦听器。
/* The function that checks whether an event listener is set for a given event. */
function listenerExists (element, event, listener) {
/* Use the element given to retrieve the record. */
var record = findRecordByElement(element);
/* Check whether a record was found & if an event array exists for the given event. */
if (record && event in record.listeners) {
/* Return whether the given listener exists. */
return !!~record.listeners[event].indexOf(listener);
}
/* Return false by default. */
return false;
}
Step 4:Finally, you will need a function that can delete a listener from the storage object.
第 4 步:最后,您将需要一个可以从存储对象中删除侦听器的函数。
/* The function that removes a listener from a given element & its storage record. */
function removeListener (element, event, listener, options) {
/* Use the element given to retrieve the record. */
var record = findRecordByElement(element);
/* Check whether any record was found and, if found, whether the event exists. */
if (record && event in record.listeners) {
/* Cache the index of the listener inside the event array. */
var index = record.listeners[event].indexOf(listener);
/* Check whether listener is not -1. */
if (~index) {
/* Delete the listener from the event array. */
record.listeners[event].splice(index, 1);
}
/* Check whether the event array is empty or not. */
if (!record.listeners[event].length) {
/* Delete the event array. */
delete record.listeners[event];
}
}
/* Add the event listener to the element. */
element.removeEventListener(event, listener, options);
}
Snippet:
片段:
window.onload = function () {
var
/* Cache the test element. */
element = document.getElementById("test"),
/* Create an event listener. */
listener = function (e) {
console.log(e.type + "triggered!");
};
/* Insert the listener to the element. */
insertListener(element, "mouseover", listener);
/* Log whether the listener exists. */
console.log(listenerExists(element, "mouseover", listener));
/* Remove the listener from the element. */
removeListener(element, "mouseover", listener);
/* Log whether the listener exists. */
console.log(listenerExists(element, "mouseover", listener));
};
<!-- Include the Custom Event Storage file -->
<script src = "https://cdn.rawgit.com/angelpolitis/custom-event-storage/master/main.js"></script>
<!-- A Test HTML element -->
<div id = "test" style = "background:#000; height:50px; width: 50px"></div>
Although more than 5 years have passed since the OP posted the question, I believe people who stumble upon it in the future will benefit from this answer, so feel free to make suggestions or improvements to it.
尽管自 OP 发布问题以来已经过去了 5 年多,但我相信将来偶然发现它的人会从这个答案中受益,因此请随时对其提出建议或改进。
回答by Paul Leclerc
You could always check manually if your EventListener exist using Chrome inspector for example. In Element tab you have the traditional "Styles" subtab and close to it another one : "Event Listeners". Which will give you the list of all EventListeners with their linked elements.
例如,您始终可以使用 Chrome 检查器手动检查您的 EventListener 是否存在。在元素选项卡中,您有传统的“样式”子选项卡,靠近它的是另一个:“事件侦听器”。这将为您提供所有 EventListeners 及其链接元素的列表。
回答by 1.21 gigawatts
It seems odd that this method doesn't exist. Is it time to add it finally?
这种方法不存在似乎很奇怪。最后是时候添加它了吗?
If you wanted to you could something like the following:
如果你愿意,你可以像下面这样:
var _addEventListener = EventTarget.prototype.addEventListener;
var _removeEventListener = EventTarget.prototype.removeEventListener;
EventTarget.prototype.events = {};
EventTarget.prototype.addEventListener = function(name, listener, etc) {
var events = EventTarget.prototype.events;
if (events[name] == null) {
events[name] = [];
}
if (events[name].indexOf(listener) == -1) {
events[name].push(listener);
}
_addEventListener(name, listener);
};
EventTarget.prototype.removeEventListener = function(name, listener) {
var events = EventTarget.prototype.events;
if (events[name] != null && events[name].indexOf(listener) != -1) {
events[name].splice(events[name].indexOf(listener), 1);
}
_removeEventListener(name, listener);
};
EventTarget.prototype.hasEventListener = function(name) {
var events = EventTarget.prototype.events;
if (events[name] == null) {
return false;
}
return events[name].length;
};
回答by dsmith63
Here's a script I used to check for the existence of a dynamically attached event listener. I used jQuery to attach an event handler to an element, then trigger that event (in this case the 'click' event). This way I can retrieve and capture event properties that will only exist if the event handler is attached.
这是我用来检查动态附加事件侦听器是否存在的脚本。我使用 jQuery 将事件处理程序附加到元素,然后触发该事件(在本例中为 'click' 事件)。通过这种方式,我可以检索和捕获仅在附加事件处理程序时才存在的事件属性。
var eventHandlerType;
$('#contentDiv').on('click', clickEventHandler).triggerHandler('click');
function clickEventHandler(e) {
eventHandlerType = e.type;
}
if (eventHandlerType === 'click') {
console.log('EventHandler "click" has been applied');
}
回答by Dave F
There doesn't appear to be a cross browser function that searches for events registered under a given element.
似乎没有跨浏览器功能来搜索在给定元素下注册的事件。
However, it is possible to view the call back functions for elements in some browsers using their development tools. This can be useful when attempting to determine how a web page functions or for debugging code.
但是,可以使用某些浏览器的开发工具查看元素的回调函数。这在尝试确定网页的功能或调试代码时非常有用。
Firefox
火狐
First, view the element in the Inspectortab within the developer tools. This can be done:
首先,在开发者工具中查看Inspector选项卡中的元素。这可以做到:
- On the pageby right clicking on the item on the web page that you want to inspect and selecting "Inspect Element" from the menu.
- Within the consoleby using a function to select the element, such as document.querySelector, and then clicking the icon beside the element to view it in the Inspectortab.
- 在页面上右键单击要检查的网页上的项目,然后从菜单中选择“检查元素”。
- 在控制台中通过使用一个函数来选择元素,例如document.querySelector,然后单击元素旁边的图标以在Inspector选项卡中查看它。
If any events were registered to the element, you will see a button containing the word Eventbeside the element. Clicking it will allow you to see the events that have been registered with the element. Clicking the arrow beside an event allows you to view the callback function for it.
如果元素注册了任何事件,您将在元素旁边看到一个包含“事件”一词的按钮。单击它将允许您查看已向元素注册的事件。单击事件旁边的箭头可以查看它的回调函数。
Chrome
铬合金
First, view the element in the Elementstab within the developer tools. This can be done:
首先,在开发人员工具的Elements选项卡中查看元素。这可以做到:
- On the pageby right clicking on the item on the web page that you want to inspect and selecting "Inspect" from the menu
- Within the consoleby using a function to select the element, such as document.querySelector, right clicking the the element, and selecting "Reveal in Elements panel" to view it in the Inspectortab.
- 在页面上右键单击要检查的网页上的项目,然后从菜单中选择“检查”
- 在控制台中通过使用一个函数来选择元素,例如document.querySelector,右键单击该元素,然后选择“在元素面板中显示”以在“检查器”选项卡中查看它。
Near the section of the window that shows the tree containing the web page elements, there should be another section with a tab entitled "Event Listeners". Select it to see events that were registered to the element. To see the code for a given event, click the link to the right of it.
在显示包含网页元素的树的窗口部分附近,应该有另一部分带有标题为“事件侦听器”的选项卡。选择它以查看注册到元素的事件。要查看给定事件的代码,请单击它右侧的链接。
In Chrome, events for an element can also be found using the getEventListenersfunction. However, based on my tests, the getEventListenersfunction doesn't list events when multiple elements are passed to it. If you want to find all of the elements on the page that have listeners and view the callback functions for those listeners, you can use the following code in the console to do this:
在 Chrome 中,还可以使用getEventListeners函数找到元素的事件。但是,根据我的测试,当多个元素传递给getEventListeners函数时,它不会列出事件。如果要查找页面上所有具有侦听器的元素并查看这些侦听器的回调函数,可以在控制台中使用以下代码来执行此操作:
var elems = document.querySelectorAll('*');
for (var i=0; i <= elems.length; i++) {
var listeners = getEventListeners(elems[i]);
if (Object.keys(listeners).length < 1) {
continue;
}
console.log(elems[i]);
for (var j in listeners) {
console.log('Event: '+j);
for (var k=0; k < listeners[j].length; k++) {
console.log(listeners[j][k].listener);
}
}
}
Please edit this answer if you know of ways to do this in the given browsers or in other browsers.
如果您知道在给定浏览器或其他浏览器中执行此操作的方法,请编辑此答案。
回答by Webwoman
If I understand well you can only check if a listener has been checked but not which listener is presenter specifically.
如果我理解得很好,您只能检查是否已检查听众,而不能检查具体是哪个听众是主持人。
So some ad hoc code would fill the gap to handle your coding flow. A practical method would be to create a state
using variables. For example, attach a listener's checker as following:
因此,一些临时代码将填补空白以处理您的编码流程。一个实用的方法是创建一个state
using 变量。例如,附加一个侦听器的检查器,如下所示:
var listenerPresent=false
then if you set a listener just change the value:
那么如果你设置了一个监听器,只需更改值:
listenerPresent=true
then inside your eventListener 's callback you can assign specific functionalities inside and in this same way, distribute the access to functionalities depending of some state as variable for example:
然后在您的 eventListener 的回调中,您可以在内部分配特定的功能,并以同样的方式,根据某些状态作为变量分配对功能的访问,例如:
accessFirstFunctionality=false
accessSecondFunctionality=true
accessThirdFunctionality=true