当DOM变化时,将addEventListener添加到所有INPUT元素

4

文档完成后,我目前正在执行以下操作。

var passwordInputs = document.querySelectorAll("input[type=password]");

for (index = 0; index < passwordInputs.length; ++index) {
    passwordInputs[index].addEventListener("focusin", activeWordsFocusIn);
    passwordInputs[index].addEventListener("focusout", activeWordsFocusOut);
}

这段代码能够如预期地工作。但是如果页面包含一些修改DOM并添加更多input元素的附加脚本,它们就无法被钩住。

如何为所有input元素添加事件处理程序,即使是通过脚本/ajax添加到DOM中的元素?

不是重复的问题我不认为这是一个重复的问题,因为这个问题Detect Changes in the DOM着重于检测DOM的变化。我的问题重点在于即使DOM更改,也要为所有input元素添加eventListener。我现在已经添加了自己的答案。


1
这与使用JS进行事件委托有关,而不是检测DOM更改。 - Ori Drori
2个回答

9
您可以使用事件委托将事件处理程序添加到输入框的容器中。当容器内的元素触发事件时,我们会检查该元素是否匹配选择器,如果匹配,则调用事件处理程序。

const delegate = (selector) => (cb) => (e) => e.target.matches(selector) && cb(e);

const inputDelegate = delegate('input[type=password]');

container.addEventListener('focusin', inputDelegate((el) => console.log('focus in', el.target.name)));

container.addEventListener('focusout', inputDelegate((el) => console.log('focus out', el.target.name)));

setTimeout(() => {
  const input = document.createElement('input');
  input.setAttribute('type', 'password');
  input.setAttribute('name', 'input2');
  
  container.append(input);
}, 2000);
<div id="container">
  <input type="password" name="input1">
</div>


干净的解决方案,谢谢 - Chrome支持matches吗? - user2233208
是的。它实际上具有非常好的支持。甚至在IE9中也得到了支持(需要加前缀)。 - Ori Drori
我以前在stackoverflow上没有看到过代码片段... container对象是什么? - user2233208
没有一个容器对象,只是对ID为“container”的DIV的引用。当在HTML中使用“id”时,会创建一个全局变量来引用该ID元素。简而言之,它就像自动的“getElementById()”函数,这也是不使用ID的非常好的理由。 - Ori Drori
明白了...不知道有没有比我建议的答案更好的优点。你的看起来更简洁,还有其他方面吗? - user2233208
我旨在使用部分应用程序实现通用和可重用性。选择器是外部的,因此您可以将其用于不同的元素。由于部分应用程序,在输入选择器后,您可以通过为每个提供回调来使用多个函数。 - Ori Drori

2

这是我找到的解决方案,它可以正常工作...

function activeWordsFocusIn(e) {
    if (isPassword(e)) {
        console.log("focus in");
    }
}

function activeWordsFocusOut(e) {
    if (isPassword(e)) {
        console.log("focus out");
    }
}

function isPassword(e) {
    var e = window.e || e;

    if (e.target.tagName !== 'INPUT')
        return false;

    if (e.target.type !== 'password')
        return false;

    return true;
}

document.addEventListener('focusin', activeWordsFocusIn, false);
document.addEventListener('focusout', activeWordsFocusOut, false);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接