AddEventListener重复触发问题:表单按钮点击重复添加书籍
问题根源与解决办法
问题原因
你每次点击.book-btn打开表单时,都会执行addButton.addEventListener("click", ...)——这意味着每触发一次.book-btn的点击事件,就会给.form-btn多绑定一个点击监听器。第一次点击.book-btn时绑定1个监听器,第二次点击就会绑定第2个,此时点击.form-btn就会同时触发这2个监听器,导致addNewBook被调用两次,次数会随着.book-btn的点击次数递增。
解决方案
最直接的修复方式是把.form-btn的事件监听器移到.book-btn的点击回调外面,只绑定一次:
const bookBtn = document.querySelector(".book-btn"); const bookContainer = document.querySelector(".book-container"); const formContainer = document.querySelector(".form-container"); // 提前获取表单提交按钮,仅绑定一次点击事件 const addButton = document.querySelector(".form-btn"); const addNewBook = (book, author, pages, read) => { const bookDiv = document.createElement("div"); bookDiv.classList.add("book"); console.log(book.value, author.value, pages.value, read.value); const h3 = document.createElement("h3"); h3.textContent = book.value; const p1 = document.createElement("p"); p1.textContent = author.value; const p2 = document.createElement("p"); p2.textContent = pages.value; const p3 = document.createElement("p"); p3.textContent = read.value; const childElements = [h3, p1, p2, p3]; for (let i = 0; i < childElements.length; i++) { bookDiv.appendChild(childElements[i]); } bookContainer.appendChild(bookDiv); formContainer.style.display = "none"; // 可选:添加后清空表单输入 book.value = ""; author.value = ""; pages.value = ""; read.value = ""; }; // 仅绑定一次表单提交按钮的点击事件 addButton.addEventListener("click", () => { const book = document.querySelector("#name"); const author = document.querySelector("#author"); const pages = document.querySelector("#pages"); const read = document.querySelector("#read"); addNewBook(book, author, pages, read); }); bookBtn.addEventListener("click", () => { formContainer.style.display = "block"; });
其他可选思路
如果因为某些原因必须在.book-btn的点击回调中绑定事件,可以每次绑定前先移除旧的监听器,但需要把回调函数提取为独立函数:
// 提取独立的回调函数 function handleAddBookClick() { const book = document.querySelector("#name"); const author = document.querySelector("#author"); const pages = document.querySelector("#pages"); const read = document.querySelector("#read"); addNewBook(book, author, pages, read); } bookBtn.addEventListener("click", () => { formContainer.style.display = "block"; const addButton = document.querySelector(".form-btn"); // 先移除旧的监听器,再绑定新的 addButton.removeEventListener("click", handleAddBookClick); addButton.addEventListener("click", handleAddBookClick); });
不过第一种方案(提前绑定一次)更简洁高效,是优先推荐的写法。
内容的提问来源于stack exchange,提问作者Palm
相关产品推荐
相关产品推荐

