[英]Detecting HTML changes when adding elements with JavaScript
我遇到了点击事件的问题。
这是代码:
for (const button of itemClick) button.addEventListener("click", function() {
clickCount++;
if (clickCount == 1) {
value1 = button.getAttribute("value");
}
if (clickCount >= 2) {
value2 = button.getAttribute("value");
clickCount = 0;
onItemClick();
}
});
itemClick 引用了一个名为 item 的文档类名变量
因此,如果我在该项目上单击两次,它应该添加第二个项目,但单击由 JavaScript 创建的项目不想工作,所以我必须以某种方式让 JavaScript 知道 Z4C4AD5FCA2E7A3F74DBB1CED0031 上它也改变了有效果,但我不知道该怎么做,也找不到任何信息。
我在 HTML 中添加元素,如下所示:
let itemDiv = document.createElement("div");
let imageDiv = document.createElement("div");
let imgEl = document.createElement("img");
let itHeading = document.createElement("h6");
let itemslistcontent = document.getElementById("items");
itemslistcontent.appendChild(itemDiv);
itemDiv.appendChild(imageDiv);
imageDiv.appendChild(imgEl);
itemDiv.appendChild(itHeading);
itemDiv.classList.add("item");
itemDiv.setAttribute("value", prop);
itHeading.innerHTML = prop;
这是完整的 function:
function onItemClick() {
for (var prop in itemNames) {
if (itemNames[prop].includes(value1) && itemNames[prop].includes(value2)) {
value1 = "";
value2 = "";
let itemDiv = document.createElement("div");
let imageDiv = document.createElement("div");
let imgEl = document.createElement("img");
let itHeading = document.createElement("h6");
let itemslistcontent = document.getElementById("items");
itemslistcontent.appendChild(itemDiv);
itemDiv.appendChild(imageDiv);
imageDiv.appendChild(imgEl);
itemDiv.appendChild(itHeading);
itemDiv.classList.add("item");
itemDiv.setAttribute("value", prop);
itHeading.innerHTML = prop;
console.log(itemslistcontent);
} else {
value1 = "";
value2 = "";
}
}
}
当您以编程方式向 DOM 添加新元素时,这些元素称为动态元素。
由于在将动态元素添加到 DOM 时您的代码已经运行,因此事件侦听器仅注册到在代码执行时已经存在的元素。
因此,您需要将事件侦听器再次添加到动态组件中。
另外,为什么不使用 JavaScript 中的dblclick
事件呢?
尝试以下代码,它在创建动态元素时添加偶数侦听器。
function onItemClick() {
for (var prop in itemNames) {
if (itemNames[prop].includes(value1) && itemNames[prop].includes(value2)) {
value1 = "";
value2 = "";
let itemDiv = document.createElement("div");
let imageDiv = document.createElement("div");
let imgEl = document.createElement("img");
let itHeading = document.createElement("h6");
let itemslistcontent = document.getElementById("items");
itemslistcontent.appendChild(itemDiv);
itemDiv.appendChild(imageDiv);
imageDiv.appendChild(imgEl);
itemDiv.appendChild(itHeading);
itemDiv.classList.add("item");
itemDiv.setAttribute("value", prop);
itHeading.innerHTML = prop;
console.log(itemslistcontent);
// adding the event listener
itemDiv.addEventListener("dblclick", function() {
value2 = button.getAttribute("value");
clickCount = 0;
onItemClick();
});
} else {
value1 = "";
value2 = "";
}
}
}
跟踪任何数量的任何元素(无论是否动态添加)上的任何事件(即"click"
)的最简单方法是使用事件委托。
注册一个元素,该元素将或包含我们想要通过"click"
事件监视/控制的所有按钮。
// Event Property document.querySelector('main').onclick = clickHandler;
或者
// EventListener document.querySelector('main').addEventListener('click', clickHandler);
每当单击此父元素时, function clickHandler()
都会运行。 此事件处理程序(只是由事件触发的 function 的更具描述性的名称)会将事件委托给用户单击的确切按钮:
使用event.target
属性来引用用户单击的元素。
通过使用if/if else/else
条件和.matches()
方法来缩小范围。
if (event.target.matches('button')) {...
我们只需要将事件注册到单个父元素。 可以使用window
和document
,但最好使用像<main>
或<form>
IMO 这样的元素。 可以使用event.currentTarget
属性引用此父元素。
const listener = event.currentTarget; console.log(listener.tagName); // MAIN
可以选择event.currentTarget
的任何后代元素。 如果用户单击了一个元素(即<button>
),则可以直接使用event.target
属性引用它。 如果所需的元素不是event.target
,而是它的邻近性,我们可以通过多种方式间接引用它。
<main> <section class='group'> <figure class='item'> <img src='pix.jpg'> <figcaption> <input> <button>X</button> <label>XXXX</label>... const clicked = event.target; if (clicked.matches('button')) { let group = clicked.closest('.group'); let item = clicked.closest('.item'); let tag = clicked.nextElementSibling; let txt = clicked.previousElementSibling; ... /* Reference to the <section>, <figure>, <input>, and <label> and finding the exact element clicked by user */
此委托还包括任何动态添加的元素。 新手常犯的一个错误是期望添加到 DOM 的元素是可点击的,但不是因为它们需要注册到事件中(即.onclick
或 .addEventListener .addEventListener('click')
)。 使用事件委托,这绝不是一个问题。 在event.currentTarget;
仅此而已。
const main = document.querySelector('main'); main.onclick = clickHandler; function clickHandler(event) { const listener = event.currentTarget; const clicked = event.target; let grpIdx = indexNodes('.group'); let itmIdx = indexNodes('.item'); const itemHTMLString = ` <figure class='item'> <img src="https://placeimg.com/100/100/any"> <figcaption> <b>Item ${itmIdx+1}</b><button>💀</button> <output class='count'>0</output> </figcaption> </figure>`; const groupHTMLString = ` <section class='group'> <fieldset> <legend>Group ${grpIdx+1} Total Clicks</legend> <output class='total'>1</output> </fieldset> <figure class='item'> <img src="https://placeimg.com/100/100/any"> <figcaption> <b>Item ${itmIdx+1}</b><button>💀</button> <output class='count'>1</output> </figcaption> </figure> </section>`; let item, group, count, total; if (clicked.matches('button')) { item = clicked.closest('.item'); group = clicked.closest('.group'); count = clicked.nextElementSibling; total = group.querySelector('.total'); let cnt = parseInt(count.textContent, 10); let ttl = parseInt(total.textContent, 10); if (ttl < 3) { total.textContent = ttl + 1; count.textContent = cnt + 1; group.insertAdjacentHTML('beforeend', itemHTMLString); indexNodes('.group'); indexNodes('.item'); } else if (ttl === 3) { let buttons = group.querySelectorAll('button'); for (let btn of buttons) { btn.disabled = true; } listener.insertAdjacentHTML('beforeend', groupHTMLString); indexNodes('.group'); indexNodes('.item'); } else { return false; } } else { return false; } } function indexNodes(selector) { const nodes = document.querySelectorAll(selector); nodes.forEach((node, index) => node.dataset.idx = index); return nodes.length; }
* { margin: 0; padding: 0; } main { margin: 10px auto; padding: 8px; }.group { display: flex; flex-flow: row nowrap; justify-content: flex-start; margin: 8px auto; padding: 4px; } fieldset { margin-top: -20px } legend { font-size: large; font-weight: bold; } figcaption { display: flex; flex-flow: row nowrap; justify-content: flex-end; } button, b, output { display: block; font-size: large; } b { text-align: left; padding: 8px 8px 0 8px; font-size: small; }.count { padding: 8px 8px 0 8px; }.total { margin: 0 auto; text-align: center; } button { cursor: pointer; max-height: 28px; }
<:DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8'> </head> <body> <main> <section class='group' data-idx='0'> <fieldset> <legend>Group 1 Total Clicks</legend> <output class='total'>1</output> </fieldset> <figure class='item' data-idx='0'> <img src="https.//placeimg;com/100/100/any"> <figcaption> <b>Item 1</b><button>💀</button> <output class='count'>1</output> </figcaption> </figure> </section> </main> </body> </html>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.