如何用原生JS处理动态生成input元素的focus等事件?
处理动态生成input元素事件的最简方案
最优方案:利用冒泡版焦点事件做委托
focus/blur这类事件本身不冒泡,但浏览器提供了对应的冒泡版事件focusin/focusout,直接在父容器(甚至document)上绑定这类事件,就能自动处理所有现有和未来新增的input,完全不用管DOM什么时候变化,比MutationObserver和HTMLCollection轮询简洁太多。
代码实现
// 直接给父容器绑定focusin事件,自动覆盖所有input document.getElementById('inputs').addEventListener('focusin', (e) => { // 只对input元素的事件做处理 if (e.target.tagName === 'INPUT') { const event = document.createElement('div'); event.innerText = `${e.type.replace('in', '')}: on ${e.target.tagName}`; events.prepend(event); } }); // 页面原有添加input的逻辑(你无需修改这段) addinput.addEventListener('click', () => { const i = document.createElement('input'); i.type = "text"; inputs.append(i); });
关于HTMLCollection的方案
HTMLCollection确实是动态更新的,但它没有内置的变化监听API,只能用定时器轮询长度变化,这种方案既不高效也不优雅,示例如下(不推荐使用):
const inputsHTMLCollection = document.getElementsByTagName('input'); let prevLength = inputsHTMLCollection.length; // 定时轮询检测元素变化 setInterval(() => { if (inputsHTMLCollection.length !== prevLength) { // 给新增的input绑定事件 for (let i = prevLength; i < inputsHTMLCollection.length; i++) { inputsHTMLCollection[i].addEventListener('focus', log); } prevLength = inputsHTMLCollection.length; } }, 100);
简化版MutationObserver方案(可选)
如果你坚持要用MutationObserver,其实可以简化写法,不用逐个解析MutationRecord,直接批量重新绑定(但还是不如事件委托简洁):
const observer = new MutationObserver(() => { // 先移除旧监听再重新绑定,避免重复触发 document.querySelectorAll('input').forEach(input => { input.removeEventListener('focus', log); input.addEventListener('focus', log); }); }); // 监听父容器的子元素变化 observer.observe(document.getElementById('inputs'), { childList: true, subtree: true });
内容的提问来源于stack exchange,提问作者Kirill
相关产品推荐
相关产品推荐

