这是我的问题:是否可以以某种方式检查是否存在一个动态附加的事件侦听器?或者我怎么能在DOM中检查“onclick”(?)属性的状态?我已经在互联网上搜索了一个解决方案,就像Stack Overflow,但没有运气。这是我的html:

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

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

document.getElementById('link2').addEventListener('click', linkclick, false);

代码运行良好,但我所有的尝试检测附加的侦听器失败:

// 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在这里。 如果你点击“Add onclick for 2”,然后点击“[link 2]”,事件会正常启动, 但是“测试链接2”总是报告错误。 有人能帮帮我吗?


当前回答

我写了3个函数来做这个:

var addEvent = function(object, type, callback)
{
    if (object != null && typeof(object) != 'undefined' && object.addEventListener)
    {
        object.isAttached = typeof object.isAttached == "undefined" ? [] : object.isAttached;
        if (!object.isAttached[type])
        {
            object.isAttached[type] = true;
            object.addEventListener(type, callback, false);
        }
    }
};

var removeEvent = function(object, type, callback)
{
    if (object != null && typeof(object) != "undefined" && typeof object.isAttached != "undefined" && object.isAttached[type])
    {
        object.removeEventListener(type, callback, false);
        object.isAttached[type] = false;
    }
};

var hasEvent = function(object, type, callback)
{
    return object != null && typeof(object) != "undefined" && typeof object.isAttached != "undefined" && object.isAttached[type];
};

函数的使用很简单:

function mousemove(e)
{
    console.log("x:" + e.clientX + ", y:" + e.clientY);
}

if (hasEvent(window, "mousemove", mousemove))
    console.log('window has "mousemove" event with "mousemove" callback');
else
    console.log('window does not have "mousemove" event with "mousemove" callback');

addEvent(window, "mousemove", mousemove);

if (hasEvent(window, "mousemove", mousemove))
    console.log('window has "mousemove" event with "mousemove" callback');
else
    console.log('window does not have "mousemove" event with "mousemove" callback');
/*
Output
window does not have "mousemove" event with "mousemove"
window has "mousemove" event with "mousemove" callback
The x and y coordinates of mouse as you move it
*/

其他回答

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

下面是Chrome浏览器的基本技巧:

getEventListeners(document.querySelector('your-element-selector'));

似乎没有跨浏览器的函数来搜索在给定元素下注册的事件。

但是,可以使用某些浏览器的开发工具查看元素的回调函数。当试图确定网页的功能或调试代码时,这可能很有用。

火狐

首先,在开发人员工具中的Inspector选项卡中查看元素。这可以做到:

在页面上右键单击要检查的网页项,并从菜单中选择“检查元素”。 在控制台中使用函数来选择元素,例如document。querySelector,然后单击元素旁边的图标在Inspector选项卡中查看它。

如果向元素注册了任何事件,您将在元素旁边看到一个包含单词Event的按钮。单击它将允许您查看已在元素中注册的事件。单击事件旁边的箭头,可以查看该事件的回调函数。

首先,在开发人员工具中的Elements选项卡中查看元素。这可以做到:

在页面上右键单击要检查的网页上的项目,并从菜单中选择“检查” 在控制台中使用函数来选择元素,例如document。querySelector,右键单击元素,选择“在元素面板中显示”,在Inspector选项卡中查看它。

在窗口中显示包含网页元素的树的部分附近,应该有另一个带有标题为“事件监听器”的选项卡的部分。选择它以查看注册到元素的事件。要查看给定事件的代码,请单击事件右侧的链接。

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

如果您知道在给定浏览器或其他浏览器中执行此操作的方法,请编辑此答案。

像这样的东西应该有助于文档:

var listeners = window.getEventListeners(document);
Object.keys(listeners).forEach(event => {
    console.log(event, listeners[event]);
});

或者使用选择器:

getAllEventListeners = function(el) {
 var allListeners = {}, listeners;

 while(el) {
  listeners = getEventListeners(el);

  for(event in listeners) {
   allListeners[event] = allListeners[event] || [];
   allListeners[event].push({listener: listeners[event], element: el});  
  }

  el = el.parentNode;
 }

 return allListeners;
}

只需删除事件,然后添加它:

document.getElementById('link2').removeEventListener('click', linkclick, false);
document.getElementById('link2').addEventListener('click', linkclick, false);

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

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

  attachEvent(domElement, 'click', this.myfunction.bind(this));
  detachEvent(domElement, 'click', this.myfunction);