将事件侦听器应用于 <divs> 时遇到问题

Having trouble applying event listeners to <divs>

大家好,我正在创建一个电子邮件应用程序,但在为每个用户将电子邮件打印到收件箱屏幕时遇到了问题。收件箱中的每封电子邮件都是 .我想为每个事件附加一个 onclick 事件侦听器,以便可以点击它,如果您点击它,您将获得一个包含电子邮件实际完整正文的页面。

我的函数 open_email() 接受一个参数,即电子邮件 ID。这就是我将用来调出电子邮件的内容。但我需要传入正确的 ID。

它现在的工作方式是 ID 始终为“1”,这是我创建的第一封电子邮件的 ID。

我不明白为什么要将每个 ID 更改为“1”。我缺少的循环中的代码一定有问题。

有人能找到吗?谢谢!

  if (mailbox == "inbox") {
    fetch('/emails/inbox')
    .then(response => response.json())
    .then(emails => {
      const element = document.getElementById("emails-view");
      for (index = 0; index < emails.length; index++) {
        var x = emails[index].id
        if (emails[index].read == false) {
          element.innerHTML += '<div class="emails unread">' + "From:" + JSON.stringify(emails[index].sender) +
          "<p class='subject'>" + "Subject: " + JSON.stringify(emails[index].subject) + "</p>" + JSON.stringify(emails[index].timestamp) + '</div>';
          element.onclick = () => open_email(x)
        }else{
          element.innerHTML += '<div class="emails">' + "From:" + JSON.stringify(emails[index].sender) +
          "<p>" + "Subject: " + JSON.stringify(emails[index].subject) + "</p>" + JSON.stringify(emails[index].timestamp) + '</div>';
          element.onclick = () => open_email(x)
        }
      }
  });

您正在向 整个容器 添加一个事件侦听器,并在循环的每次迭代中覆盖它。相反,向附加元素添加一个侦听器。

一个问题是使用 innerHTML += 会破坏容器内的现有侦听器,因此请改用 appendChild

const container = document.getElementById("emails-view");
for (const email of emails) {
    const { read, id, timestamp, sender, subject } = email;
    const emailDiv = container.appendChild(document.createElement('div'));
    emailDiv.className = read ? 'emails' : 'emails unread';
    emailDiv.innerHTML = `
        From: ${JSON.stringify(sender)}
        <p class='subject'>Subject: ${JSON.stringify(subject)}</p> ${timestamp}
    `;
    emailDiv.onclick = () => open_email(id);
}

这是一般的想法 - 但还有另一个问题。连接来自用户输入的 HTML 个字符串会导致任意代码执行。为防止不安全代码成为 运行,请确保放入 HTML 的值不包含 HTML 标记定界符(<>) .

const clean = str => str
  .replaceAll('<', '&lt;')
  .replaceAll('>', '&gt;');

并使用,例如:

From: ${JSON.stringify(clean(sender))}

或者,更好的是,在将文本放入数据库之前对其进行清理。

(你真的到处都需要 JSON.stringify 吗?这看起来很奇怪,如果可以的话请删除它)