【问题标题】:How to add event listener with HTML template literals in Javascript?如何在 Javascript 中使用 HTML 模板文字添加事件侦听器?
【发布时间】:2021-10-12 09:02:29
【问题描述】:

我从一个 URL 中获取了一些数据,之后我使用forEach 循环为每个接收到的数据项生成了一个 HTML 模板。在为响应数据中的所有元素创建 HTML 模板后,我已将其分配给 document.body.innerHTML。所以它会用我的 HTML 模板显示所有元素。

响应有 30 个对象,每个对象都有一个链接 (clone_url) 与其他信息。我使用我的 HTML 模板为这 30 个对象生成了 HTML 元素,每个对象都有一个名称、个人资料头像和用于复制我提到的特定链接的按钮。当用户单击复制按钮时,我想将该链接复制到剪贴板中。

因此,我想向按钮添加事件侦听器。那就是我一直在努力的地方,因为我不知道该怎么做。因为我必须访问每个组件,并且我想访问相关的响应对象来获取链接。

const url = "https://api.github.com/users/shrutikapoor08/repos";

fetch(url)
  .then((response) => response.json())
  .then((users) => {
    console.log(users);
    let htmlText = "";
    users.forEach((i) => {
      htmlText += `
        <div class="repo-container">
        <p class="repo-title">${i.name}</p>
        <div class="repo-owner">
          <img
            src="${i.owner.avatar_url}"
            alt="avatar"
            class="avatar"
          />
          <a href="${i.owner.html_url}" class="repo-owner-username">${i.owner.login}</a>
        </div>
        <div class="link-container">
          <button class="repo-link-btn">Copy</button>
          <p class="tooltip">Link Coppied</p>
        </div>
      </div>
        `;
    });
    document.body.innerHTML = htmlText;
  });
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: "Roboto", sans-serif;
}

.repo-container {
  background-color: rgb(255, 253, 251);
  border: 1px solid rgb(226, 226, 226);
  padding: 15px;
  width: 250px;
  margin: 10px;
}

.repo-title {
  font-weight: bold;
  margin-bottom: 10px;
}

.repo-owner {
  display: flex;
  align-items: center;
}

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  margin-right: 20px;
}

.repo-owner-username {
  font-size: 0.8rem;
  text-decoration: none;
}

.tooltip {
  background-color: rgba(0, 0, 0, 0.7);
  width: fit-content;
  padding: 4px 10px;
  border-radius: 10px;
  font-size: 0.75rem;
  color: white;
  opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
  pointer-events: none;
}

.tooltip.active {
  opacity: 1;
  transform: translateY(-10px);
}

.link-container {
  display: flex;
}

.repo-link-btn {
  margin: 10px 0px;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./style.css" />
    <title>Document</title>
  </head>
  <body>
    <script src="./app.js"></script>
  </body>
</html>

这是我想为每个按钮添加的代码。

document.querySelector(".repo-link-btn").addEventListener("click", async () => {
  const text = "";
  await navigator.clipboard.writeText(text);
  document.querySelector(".tooltip").classList.add("active");
  setTimeout(() => {
    document.querySelector(".tooltip").classList.remove("active");
  }, 500);
});

const text 应该等于响应数据对象的 URL。我也必须访问这些数据。解决这个问题的好习惯是什么?

【问题讨论】:

  • Event delegation。向父元素添加一个侦听器,而不是向大量元素添加大量侦听器。事件将 DOM 冒泡到捕获它们的父侦听器。然后,您可以根据事件中的信息确定要采取的操作。
  • @Andy 但最后我如何才能访问获取的响应数据以获取到每个组件的特定链接?因为在事件监听器中我想访问相关的响应数据。 ??????

标签: javascript event-listener template-literals html-templates


【解决方案1】:

如果你想使用纯 JavaScript,你需要创建循环并向所有项目添加事件侦听器,如下所示:

[...document.querySelectorAll(".repo-link-btn")].forEach(function (item) {..}

要找到clone_url 值,您可以设置自定义属性,例如data-cloneUrl="${i.clone_url}",然后在点击时获取它:e.target.getAttribute("data-cloneUrl");

请注意,此代码基于您的 html 和纯 JavaScript。 jQuery有更简单的方法。

        const url = "https://api.github.com/users/shrutikapoor08/repos";

        fetch(url)
            .then((response) => response.json())
            .then((users) => {
                console.log(users);
                let htmlText = "";
                users.forEach((i) => {
                    htmlText += `
        <div class="repo-container">
        <p class="repo-title">${i.name}</p>
        <div class="repo-owner">
          <img
            src="${i.owner.avatar_url}"
            alt="avatar"
            class="avatar"
          />
          <a href="${i.owner.html_url}" class="repo-owner-username">${i.owner.login}</a>
        </div>
        <div class="link-container">
          <button class="repo-link-btn" data-cloneUrl="${i.clone_url}">Copy</button>
          <p class="tooltip">Link Coppied</p>
        </div>
      </div>
        `;
                });
                document.body.innerHTML = htmlText;

                [...document.querySelectorAll(".repo-link-btn")].forEach(function (item) {
                    item.addEventListener("click", async (e) => {
                        const text = e.target.getAttribute("data-cloneUrl");
                        await navigator.clipboard.writeText(text);
                        document.querySelector(".tooltip").classList.add("active");
                        setTimeout(() => {
                            document.querySelector(".tooltip").classList.remove("active");
                        }, 500);
                    });
                })
            });
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap");

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: "Roboto", sans-serif;
        }

        .repo-container {
            background-color: rgb(255, 253, 251);
            border: 1px solid rgb(226, 226, 226);
            padding: 15px;
            width: 250px;
            margin: 10px;
        }

        .repo-title {
            font-weight: bold;
            margin-bottom: 10px;
        }

        .repo-owner {
            display: flex;
            align-items: center;
        }

        .avatar {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            margin-right: 20px;
        }

        .repo-owner-username {
            font-size: 0.8rem;
            text-decoration: none;
        }

        .tooltip {
            background-color: rgba(0, 0, 0, 0.7);
            width: fit-content;
            padding: 4px 10px;
            border-radius: 10px;
            font-size: 0.75rem;
            color: white;
            opacity: 0;
            transition: transform 0.3s ease, opacity 0.3s ease;
            pointer-events: none;
        }

            .tooltip.active {
                opacity: 1;
                transform: translateY(-10px);
            }

        .link-container {
            display: flex;
        }

        .repo-link-btn {
            margin: 10px 0px;
        }

请注意,sn-p 工作正常但堆栈溢出 sn-p 说The Clipboard API has been blocked because of a permissions policy applied to the current document。所以检查你电脑里的sn-p。

【讨论】:

  • @Kasun 你的问题解决了吗?如果有问题请告诉我
  • 是的,这行得通! ? 但我不明白它是如何工作的。我不明白它是如何在foreach 循环之后访问响应数据对象的。 e.target.parentElement.previousElementSibling.getElementsByTagName('a')[0].getAttribute("href"); 这个东西如何访问那个 url。
  • @Kasun 别担心,我会为您解释。当你创建一个事件时,回调函数参数是事件(比如e 这里)。 e.target 是您单击它的目标。这是button。但是您的链接位于按钮父级的上一个兄弟中:)。我的意思是div"repo-owner"
  • @Kasun 所以首先我得到按钮的父级,它是带有link-container 类的div,然后我尝试访问previousElementSibling,它是带有repo-owner 类的div。 e.target.parentElement.previousElementSibling
  • 最后阶段是从repo-owner类获取锚标签,即:getElementsByTagName('a')。我希望我的解释对你来说很清楚
猜你喜欢
  • 2021-09-09
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多