如何检查动态连接的事件监听器是否存在?

Sta*_*ano 68 javascript testing addeventlistener dom-events

这是我的问题:是否有可能以某种方式检查动态附加事件监听器的存在?或者我如何检查DOM中"onclick"(?)属性的状态?我已经像StackOverflow一样搜索了互联网,但是没有运气.这是我的HTML:

<a id="link1" onclick="linkclick(event)"> link 1 </a>
<a id="link2"> link 2 </a> <!-- without inline onclick handler -->
Run Code Online (Sandbox Code Playgroud)

然后在javascript中我将动态创建的事件监听器附加到第二个链接:

document.getElementById('link2').addEventListener('click', linkclick, false);
Run Code Online (Sandbox Code Playgroud)

代码运行良好,但我检测连接的侦听器的所有尝试都失败了:

// 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?
Run Code Online (Sandbox Code Playgroud)

jsFiddle就在这里.如果单击"添加onclick for 2"然后单击"[link 2]",则事件会激活,但"测试链接2"始终报告为false.有人可以帮忙吗?

Iva*_*van 36

无法检查是否存在动态连接的事件侦听器.

您可以看到附加事件侦听器的唯一方法是附加事件侦听器,如下所示:

elem.onclick = function () { console.log (1) }
Run Code Online (Sandbox Code Playgroud)

然后,您可以onclick通过返回!!elem.onclick(或类似的东西)来测试是否附加了事件侦听器.

  • @JonRaynor如果你想将它转换为布尔值,你需要它. (7认同)

小智 21

我做了类似的事情:

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');
    });
}
Run Code Online (Sandbox Code Playgroud)

在附加侦听器时为元素创建特殊属性,然后检查它是否存在.

  • 我可能会很愚蠢(对此有 74 票赞成),但我认为 `elementClicked.setAttribute('listener', 'true');` 应该添加到 `addEventListender` 函数之外 - 否则它仅在事件发生时添加被触发,因此实际上不允许您检查事件侦听器是否已可靠附加。 (29认同)
  • 这是我过去使用的方法。我的建议是使用非常具体的语法结构。IE而不是“侦听器”,请使用事件本身。因此,“数据事件单击”。这在您要执行多个事件时提供了一定的灵活性,并使事情更具可读性。 (2认同)
  • 这与 @conrad10781 的添加似乎是最可靠和最简单的方法。如果由于某种原因元素被重新渲染并且事件侦听器断开连接,则该属性也将被重置。 (2认同)

Ces*_*sar 18

我要做的是在函数外部创建一个布尔值为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);
 }
}
Run Code Online (Sandbox Code Playgroud)


aru*_*ian 12

可能的重复:检查元素上是否有事件侦听器。没有 jQuery 请在那里找到我的答案。

基本上这里是 Chromium (Chrome) 浏览器的技巧:

getEventListeners(document.querySelector('your-element-selector'));
Run Code Online (Sandbox Code Playgroud)

  • 更准确地说,在这里:/sf/answers/2879630981/。 (2认同)

1.2*_*tts 7

这种方法不存在似乎很奇怪。最后是时候添加它了吗?

如果你愿意,你可以像下面这样:

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;
};
Run Code Online (Sandbox Code Playgroud)


Ang*_*tis 6

tl; dr:否,您不能以任何本机支持的方式执行此操作。


我知道实现此目标的唯一方法是创建一个自定义存储对象,在其中保存添加的侦听器的记录。遵循以下内容:

/* Create a storage object. */
var CustomEventStorage = [];
Run Code Online (Sandbox Code Playgroud)

步骤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;
}
Run Code Online (Sandbox Code Playgroud)

步骤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);
}
Run Code Online (Sandbox Code Playgroud)

步骤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;
}
Run Code Online (Sandbox Code Playgroud)

步骤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);
}
Run Code Online (Sandbox Code Playgroud)

片段:

/* Create a storage object. */
var CustomEventStorage = [];
Run Code Online (Sandbox Code Playgroud)
/* 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;
}
Run Code Online (Sandbox Code Playgroud)


尽管自OP发布该问题以来已经过去了5年多,但我相信将来迷失于此问题的人们将从该答案中受益,因此随时可以提出建议或对其进行改进。


Pau*_*erc 5

例如,您可以使用Chrome检查器手动检查EventListener是否存在.在"元素"选项卡中,您可以使用传统的"样式"子选项卡,并在其旁边显示另一个:"事件监听器".这将为您提供所有EventListener及其链接元素的列表.


min*_*eek 5

2022 年更新:

我根据这个答案在 TypeScript 中编写了实用方法来附加和分离事件,但这是一个更正的答案。希望有人觉得它有帮助。

export const attachEvent = (
  element: Element,
  eventName: string,
  callback: () => void
) => {
  if (element && eventName && element.getAttribute('listener') !== 'true') {
    element.setAttribute('listener', 'true');
    element.addEventListener(eventName, () => {
      callback();
    });
  }
};

export const detachEvent = (
  element: Element,
  eventName: string,
  callback: () => void
) => {
  if (eventName && element) {
    element.removeEventListener(eventName, callback);
  }
};

Run Code Online (Sandbox Code Playgroud)

导入它并像这样在任何地方使用它

  attachEvent(domElement, 'click', this.myfunction.bind(this));
  detachEvent(domElement, 'click', this.myfunction);
Run Code Online (Sandbox Code Playgroud)

  • 这可以防止添加不同类型的侦听器,例如 mouseenter/leave,因此您可能需要设置“listener”+eventName 属性,而不仅仅是“listener” (2认同)