如何为未来的 DOM 元素添加事件监听器?

问题描述 投票:0回答:2

文件partial.html看起来像这样:

<button id="test">Hi I am from a partial!</button>

Partial.html
动态包含在页面上,使用
XMLHttpRequest
:

var oReq = new XMLHttpRequest();
oReq.open('get', 'partial.html', true);
oReq.send();
oReq.onload = function() {
  document.querySelector('#pageArea').innerHTML = this.response;
};

如何添加适用于未来现有

#test
的事件侦听器,而无需在内容加载并插入到
#pageArea
后执行此操作?

(请不要使用 jQuery 解决方案!)

javascript event-listener
2个回答
20
投票

类似 click bubble 的事件,因此您可以将事件处理程序附加到最近的非动态父级,并在事件处理程序内通过查看是否是事件的目标来检查是否是被单击的按钮:

var parent = document.getElementById('pageArea');

if (parent.addEventListener) {
    parent.addEventListener('click', handler, false);
}else if (parent.attachEvent) {
    parent.attachEvent('onclick', handler);
}

function handler(e) {
    if (e.target.id == 'test') {
         // the button was clicked
    }
}

小提琴


2
投票

不要只是使用

Event.target

正如我在网上找到的许多其他答案错误地建议的那样,Event.target很可能是不需要的子元素
例如:
<button class="dynamic" type="button">CLICK <i>ME!</i></button>

如果你点击按钮的“ME!”部分——你的逻辑将会彻底失败。

始终将

Event.target
.closest()

结合使用
document.querySelector("#staticParent").addEventListener("click", evt => {
  if (event.target.closest(".dynamic")) {
    // The desired button (or its child) was clicked!
  }
});

创建您自己的
on()
off()
辅助函数:

对于动态创建的元素,在插入 DOM 之前要对其分配单击事件 - 将事件分配给父委托者,然后查询事件

Event.target.closest(selector)
与所需的动态子选择器匹配:

const _ev = (type, name, delegator, ...arg) => {
  if (typeof delegator === "string") return document.querySelectorAll(delegator).forEach(el => _ev(type, name, el, ...arg));
  if (typeof arg[0] === "string") delegator[type](name, ev => ev.target.closest(arg[0]) && arg[1](ev), arg[2]);
  else delegator[type](name, arg[0], arg[1]);
};
const on = (...arg) => _ev("addEventListener", ...arg);
const off = (...arg) => _ev("removeEventListener", ...arg);


// Use like:

on("click", "#staticParent", ".dynamicChild", (ev) => {
  console.log(ev.currentTarget, ev.target);
});

on("click", ".test", (ev) => {
  console.log(ev.currentTarget);
}, { once: true });
body * { padding: 0.5rem; background: #0002; margin: 0.2rEm; }
<div id="staticParent"> Parent
  <div class="dynamicChild">Existent or dynamic Child (Clickable)</div>
</div>

<div class="test">Test 1 (I'm only clickable once)</div>

© www.soinside.com 2019 - 2024. All rights reserved.