在动态创建的元素上添加事件侦听器

IT技术 javascript addeventlistener dom-events intercept
2021-02-06 22:44:20

是否可以向所有动态生成的元素添加事件侦听器 (Javascript)?我不是页面的所有者,因此我无法以静态方式添加侦听器。

对于页面加载时创建的所有元素,我使用:

doc.body.addEventListener('click', function(e){
//my code
},true);

当页面上出现新元素时,我需要一种方法来调用此代码,但我无法使用 jQuery(delegate、on 等无法在我的项目中工作)。我怎样才能做到这一点?

6个回答

听起来您需要在不退回到图书馆的情况下采用委托策略。我在这里的 Fiddle 中发布了一些示例代码:http : //jsfiddle.net/founddrama/ggMUn/

它的要点是使用对象target上的event来查找您感兴趣的元素,并做出相应的响应。就像是:

document.querySelector('body').addEventListener('click', function(event) {
  if (event.target.tagName.toLowerCase() === 'li') {
    // do your action on your 'li' or whatever it is you're listening for
  }
});

注意事项!示例 Fiddle 仅包含符合标准的浏览器(即 IE9+,以及几乎所有其他版本的所有版本)的代码 如果您需要支持“旧 IE” attachEvent,那么您还需要提供自己的自定义包装器适当的本机功能。(关于这个有很多很好的讨论;我喜欢 Nicholas Zakas 在他的书Professional JavaScript for Web Developers 中提供的解决方案。)

@drinchev 是的,它们都是等价的。在给出示例时,我更喜欢使用document.querySelector()版本,因为这样更易于概括——即,并非每个元素都可以document作为属性从 中访问
2021-03-23 22:44:20
很好的答案,我想知道不只是document.body === document.querySelector('body')这就是为什么在这两种情况下,您总是将一个单击处理程序附加到唯一的一个 body 元素。
2021-03-30 22:44:20
@ColorWin 您需要使用事件捕获
2021-03-31 22:44:20
@JianWeihang 你能澄清一下你的问题吗?您不想将元​​素直接应用于body元素(例如,作为onclick属性),否则会冒着吹走已经存在的侦听器的风险。事件委托策略要安全得多:不太可能干扰或破坏元素上的其他侦听器,并且不太可能用每个元素的侦听器占用内存。
2021-04-04 22:44:20
如果我的事件是focus,它似乎不起作用。我应该怎么做?
2021-04-06 22:44:20

取决于您如何添加新元素。

如果你添加 using createElement,你可以试试这个:

var btn = document.createElement("button");
btn.addEventListener('click', masterEventHandler, false);
document.body.appendChild(btn);

然后你可以用它masterEventHandler()来处理所有的点击。

迄今为止最好的答案。
2021-03-14 22:44:20
我不是添加元素的页面的所有者,所以我不知道元素的插入方式。
2021-04-05 22:44:20
我在这个答案中看到的问题是,当/如果删除底层元素时,事件侦听器仍将保留在内存中。这是因为对 的引用btn仍然存在。在这种情况下,选择的答案是更好的答案。请参阅此处了解更多信息。
2021-04-08 22:44:20

这里值得注意的一个隐晦问题也可能是我刚刚发现的这个事实:

如果某个元素z-index设置为-1或更小,您可能会认为侦听器没有被绑定,而实际上是这样,但浏览器认为您正在单击更高的z-index元素。

在这种情况下,问题不是侦听器没有被绑定,而是它无法获得焦点,因为其他东西(例如,可能是隐藏元素)在您的元素之上,并且get 是焦点(意思是:事件没有被触发)。幸运的是,您可以通过右键单击元素,选择“检查”并检查您单击的内容是否正在“检查”来轻松检测到这一点。

我用的是Chrome,不知道其他浏览器有没有这么受影响。但是,很难找到,因为在功能上,它在大多数方面都类似于侦听器未绑定的问题。我固定它通过CSS删除行: z-index:-1;

我创建了一个小函数来添加动态事件侦听器,类似于jQuery.on().

它使用与接受的答案相同的想法,只是它使用该Element.matches()方法来检查目标是否与给定的选择器字符串匹配。

addDynamicEventListener(document.body, 'click', '.myClass, li', function (e) {
    console.log('Clicked', e.target.innerText);
});

你可以从 github获取

将匿名任务委托给动态创建HTML elementsevent.target.classList.contains('someClass')

  1. 返回truefalse
  2. 例如。
let myEvnt = document.createElement('span');
myEvnt.setAttribute('class', 'someClass');
myEvnt.addEventListener('click', e => {
  if(event.target.classList.contains('someClass')){ 
    console.log(${event.currentTarget.classList})
}})
  1. 参考:https : //gomakethings.com/attaching-multiple-elements-to-a-single-event-listener-in-vanilla-js/
  2. 好读物:https : //eloquentjavascript.net/15_event.html#h_NEhx0cDpml
  3. MDN:https : //developer.mozilla.org/en-US/docs/Web/API/Event/Comparison_of_Event_Targets
  4. 插入点: