文件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 解决方案!)
类似 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
}
}
不要只是使用
Event.target
!<button class="dynamic" type="button">CLICK <i>ME!</i></button>
始终将
与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>