Javascript 如何在DOM[no jQuery]中尚未包含的元素上添加事件侦听器?
我想将事件侦听器(调用函数)附加到DOM中尚未出现的按钮。我不想在HTML中使用内联调用,我该怎么做 到目前为止,我可以通过创建一个Javascript 如何在DOM[no jQuery]中尚未包含的元素上添加事件侦听器?,javascript,html,Javascript,Html,我想将事件侦听器(调用函数)附加到DOM中尚未出现的按钮。我不想在HTML中使用内联调用,我该怎么做 到目前为止,我可以通过创建一个全局事件监听器来实现我想要的,该监听器检查单击的元素是否具有特定的Id。但是我发现这个解决方案是肮脏的,不是最优的 const messageForm = document.querySelector("#message-form") const messageTextarea = document.querySelector("#message-textarea"
全局事件监听器来实现我想要的,该监听器检查单击的元素是否具有特定的Id。但是我发现这个解决方案是肮脏的,不是最优的
const messageForm = document.querySelector("#message-form")
const messageTextarea = document.querySelector("#message-textarea");
const messageList = document.querySelector("#message-list");
const messageEmpty = document.querySelector("#message-empty");
let messageNumber = 0;
const messageFormatted = messageText => {
return `
<li class="message-item">
<img class="message-avatar" src="./icons/boy.png" alt="Username">
<article class="message-content">
<p class="author">Ernesto Campese</p>
<p class="message">${messageText}</p>
<p class="datetime">A moment ago</p>
</article>
<div class="message-actions">
<img id="message-edit" class="action-button" src="./icons/edit.png" alt="" width="22" height="22">
<img id="message-delete" class="action-button" src="./icons/delete.png" alt="" width="22" height="22">
</div>
</li>
`;
}
document.addEventListener("click", (e) => {
if (e.target.id === "message-delete") {
e.target.parentNode.parentNode.remove();
messageNumber--;
messageEmptyCheck();
}
})
messageForm.addEventListener("submit", (e) => {
e.preventDefault();
if (messageTextarea.value !== "") {
messageList.insertAdjacentHTML("beforeend", messageFormatted(messageTextarea.value));
messageTextarea.value = null;
messageTextarea.focus();
messageNumber++;
messageEmptyCheck();
}
});
希望我说得够清楚,谢谢你们 你在正确的轨道上。识别特征不必是id
,它可以是关于元素的任何东西-类是一种常见的方法
有三种DOM方法可以帮助实现灵活:
- -从您调用它的元素开始,它查找与给定CSS选择器匹配的最近祖先
- -检查节点是否包含其他节点
- -检查调用它的元素是否与给定的CSS选择器匹配
例如,当前处理程序要求按钮是单击的元素(event.target
)。这对于您的img
用例来说很好,但是如果它是一个按钮,里面有一个img
,会怎么样?然后,event.target
可能是img
的按钮,具体取决于用户单击的位置<代码>最近的
和包含以下帮助:
document.addEventListener("click", (e) => {
const button = e.target.closest("#message-delete");
if (button) {
button.closest("li").remove();
messageNumber--;
messageEmptyCheck();
}
})
您还需要将事件挂接到最近的容器上。有时候,你会被document
或document.body
所困扰。但通常情况下,你可以做得更好。例如,当在表格单元格中的按钮上侦听按钮单击时,您可以在表格
或t正文
/而不是文档级别侦听。这就是contains
进入等式的地方,它确保了最近的
不会在文档树上走得太远:
document.querySelector("selector-for-the-table").addEventListener("click", (e) => {
const button = e.target.closest("#message-delete");
if (button && e.currentTarget.contains(button)) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
button.closest("li").remove();
messageNumber--;
messageEmptyCheck();
}
})
在您的情况下,对#message delete
的搜索不太可能超出包含元素,因此您可能不需要该位,但有时也会发生这种情况,因此您希望包含检查。如果您真的想将事件侦听器添加到该元素本身,那么我认为您可能需要尝试使用MutationObserver-
您可以通过传递config for childList、subtree来观察事件,并在事件上检查您要查找的元素是否已添加或存在。如果您发现可以添加事件侦听器
你可能想看看以下文章-
我希望这会有所帮助。您可以将HTML字符串解析为JS中的文档
,然后将事件侦听器添加到该元素中
这样就得到了模板文本字符串
const messageFormatted = messageText => {
return `
<li class="message-item">
<img class="message-avatar" src="./icons/boy.png" alt="Username">
<article class="message-content">
<p class="author">Ernesto Campese</p>
<p class="message">${messageText}</p>
<p class="datetime">A moment ago</p>
</article>
<div class="message-actions">
<img id="message-edit" class="action-button" src="./icons/edit.png" alt="" width="22" height="22">
<img id="message-delete" class="action-button" src="./icons/delete.png" alt="" width="22" height="22">
</div>
</li>
`;
}
这个文档的工作原理与页面中的文档类似,它只是一个新文档,目前只存在于JS内存中。将您的string
作为参数提供给parseStringToHTML
以创建HTML
const message = messageFormatted('This is the message'); // Example message
const messageHTML = parseStringToHTML(message); // Returns a document object with all the features a document object has.
因此,既然您的字符串
是一个文档
,您可以在其上使用类似getElementById
、querySelector
等方法。但是首先必须选择所需的元素
const messageDeleteButton = messageHTML.querySelector("#message-delete");
请注意,我使用了messageHTML
而不是document
。在这个场景中,messageHTML
是一个文档
,因此我们可以在其中查询。现在您已经在这个文档中找到了您的元素
,您可以向其中添加一个事件侦听器
messageDeleteButton.addEventListener("click", (e) => {
e.parentNode.parentNode.remove();
});
好的,现在已经添加了事件侦听器。您现在需要做的就是将messageHTML
中所需的HTML附加到页面的文档中。HTML可以在messageHTML.body
属性中找到
现在,不要使用insertAdjacentHTML
在您选择的位置插入元素。要附加的元素是
,它将是messageHTML.body
属性的正文中的firstElementChild
因此,在表单的submit
事件侦听器中,更改以下行:
messageList.insertAdjacentHTML("beforeend", messageFormatted(messageTextarea.value));
以上我已经解释过了
// Create string
const message = messageFormatted(messageTextarea.value);
// String to document
const messageHTML = parseStringToHTML(message);
// Select delete element.
const messageDeleteButton = messageHTML.querySelector("#message-delete");
// Add event listener to delete element.
messageDeleteButton.addEventListener("click", (e) => {
e.parentNode.parentNode.remove();
});
// Append the <li> element to the messageList.
messageList.insertAdjacentElement("beforeend", messageHTML.body.firstElementChild);
//创建字符串
const message=messageFormatted(messageTextarea.value);
//字符串到文档
const messageHTML=parseStringToHTML(消息);
//选择删除元素。
const messageDeleteButton=messageHTML.querySelector(“#message delete”);
//添加事件侦听器以删除元素。
messageDeleteButton.addEventListener(“单击”,(e)=>{
e、 parentNode.parentNode.remove();
});
//将元素附加到messageList。
insertAdjacentElement(“beforeend”,messageHTML.body.firstElementChild);
不要忘记在代码中包含parseStringToHTML
函数。我知道这是一个很大的工作,所以如果你有任何问题,请问
我希望这能帮助你
注意我发现事件委派(全局事件侦听器)不是您想要做的事情,尽管正如其他人所说,它比其他方法(甚至是我自己的答案)更高效、更容易实现。它还可以解决监听您在列表中添加甚至删除的元素的问题。您甚至可以在
元素上设置它,如T.J.Crowder建议将侦听器附加到文档级别而不是元素level@ImmortalDude-请看问题中的代码。让我这样说,如果您将这样的文档与多个事件侦听器连接起来,你迟早会遇到麻烦的。图像中有一个消息删除按钮、消息投票按钮、消息等等。这并不是批评您,而是针对引擎在文档或容器中的每次单击
messageList.insertAdjacentHTML("beforeend", messageFormatted(messageTextarea.value));
// Create string
const message = messageFormatted(messageTextarea.value);
// String to document
const messageHTML = parseStringToHTML(message);
// Select delete element.
const messageDeleteButton = messageHTML.querySelector("#message-delete");
// Add event listener to delete element.
messageDeleteButton.addEventListener("click", (e) => {
e.parentNode.parentNode.remove();
});
// Append the <li> element to the messageList.
messageList.insertAdjacentElement("beforeend", messageHTML.body.firstElementChild);