为什么在 JavaScript 中动态生成的按钮上会多次调用函数?

问题描述 投票:0回答:1

我正在制作一个从 Google Places API 绘制搜索结果列表的应用程序,这使用户有机会使用 JavaScript 动态生成的按钮将位置标记为已访问(然后存储在 MongoDB 中)。当我单击该按钮时,我看到该事件已运行大约 20 次(顺便说一句,搜索结果中返回了相同数量的位置)。然后,这会调用服务器端的 API 端点大约 5 次。

我怀疑这与将事件侦听器绑定到每个单独的按钮有关,但我不确定解决方法是什么。非常感谢任何帮助!

客户端功能:

              const markVisitedButtons = document.querySelectorAll(".visitor");
              markVisitedButtons.forEach((button) => {
                button.addEventListener("click", function () {
                  console.log("eventlistener");
                  const placeId = this.getAttribute("data-place-id");
                  const placeName = this.getAttribute("placeName");
                  const placeAddress = this.getAttribute("placeAddress");
                  markVisited(placeName);
                });
              });
              function markVisited(placeName) {
                console.log("fetch function");
                fetch(`/markVisited`, {
                  method: "POST",
                  headers: {
                    "Content-Type": "application/json",
                  },
                  body: JSON.stringify({ placeName }),
                })
                  .then((response) => response.json())
                  .then((data) => {
                    console.log(data);
                  })
                  .catch((error) => {
                    console.log(error);
                  });
              }

以及在获取之后调用的服务器端函数:

router.post("/markVisited", async (req, res, next) =\> {
    const placeName = req.body;

          try {
            const newPlace = await new VisitedPlace({
              placeName: req.body.placeName,
              userId: req.user._id,
            });
    
            newPlace
              .save()
              .then(
                User.updateOne(
                  { _id: req.user._id },
                  { $push: { visitedPlaces: newPlace._id } }
                )
              );
          } catch (error) {
            console.log(error);
          }
        });
javascript html node.js dom
1个回答
0
投票

要解决此问题,您可以尝试使用事件委托。事件委托意味着将单个事件侦听器附加到按钮的公共父元素,然后使用事件对象来确定单击了哪个特定按钮。

这是您的客户端功能:

const markVisitedButtonsContainer = document.querySelector(".container"); // Use a common parent element
markVisitedButtonsContainer.addEventListener("click", function (event) {
  if (event.target.classList.contains("visitor")) {
    const placeId = event.target.getAttribute("data-place-id");
    const placeName = event.target.getAttribute("placeName");
    const placeAddress = event.target.getAttribute("placeAddress");
    markVisited(placeName);
  }
});



function markVisited(placeName) {
  console.log("fetch function");
  fetch(`/markVisited`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ placeName }),
  })
    .then((response) => response.json())
    .then((data) => {
      console.log(data);
    })
    .catch((error) => {
      console.log(error);
    });
}

我添加了一个容器元素(将 .container 替换为保存按钮的容器的实际类或 id)作为按钮的公共父元素。事件侦听器附加到此容器,并检查单击的元素是否具有类访问者。如果是,则处理该事件。这样,您就可以确保无论有多少按钮,您都只有一个事件侦听器,并且该事件不会多次传播。

© www.soinside.com 2019 - 2024. All rights reserved.