You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:20:27