【问题标题】:Add an element with addEventListener and get it in the next iteration [duplicate]使用 addEventListener 添加一个元素并在下一次迭代中获取它[重复]
【发布时间】:2019-01-18 07:04:36
【问题描述】:

我在所有带有“card-title”类的html元素上添加了一个事件监听器,这个监听器用于创建与“card-title”类相同的html元素,但是这些新创建的元素不响应addEventListener当我点击它们时。我猜是因为它们没有添加到数组cardTitles中,我不知道该怎么做

function myFunc() {
  var cardTitles = document.getElementsByClassName('card--title');

  for (var i = 0; i < cardTitles.length; i++) {
    cardTitles[i].addEventListener('click', function() {
      var newCard = document.createElement('p');
      newCard.className = 'card--title';
      newCard.innerText = 'Enter';
      document.body.appendChild(newCard);
    });
  }
}

myFunc();

【问题讨论】:

  • 使用事件委托:document.addEventListener("click", function(e){ if(e.target.matches(".card--title")){ /* Do click listener things */ } }).

标签: javascript html arrays dom addeventlistener


【解决方案1】:

我猜是因为它们没有添加到数组cardTitles中,我不知道该怎么做

实际上,它们是(如果浏览器原生支持getElementsByClassName,而不是polyfill);它返回一个live HTMLCollection

不过,没有发生的是,您没有将事件侦听器挂接到这些新元素上。你的循环只运行一次,处理那里的元素然后,当你添加元素时它不会重新运行。

你有两个选择:

  1. 在添加元素时将处理程序添加到每个新元素,或者

  2. 在所有这些都在的容器上使用 single 处理程序,并使用event.target 确定点击了哪个,因为点击会冒泡;这称为事件委托

这是#1 的一个简单示例:

function myFunc() {
  function handler() {
    var newCard = document.createElement('p');
    newCard.className = 'card--title';
    newCard.innerText = 'Enter';
    newCard.addEventListener('click', handler);
    document.body.appendChild(newCard);
  }

  var cardTitles = document.getElementsByClassName('card--title');

  for (var i = 0; i < cardTitles.length; i++) {
    cardTitles[i].addEventListener('click', handler);
  }
}

myFunc();

这是#2 的一个简单示例:

function myFunc() {
  var container = document.querySelector("selector-for-the-container");
  // For your use case, you probably can just use `document.body` instead
  // of `container`, since you're appending new card titles to `document.body`

  container.addEventListener('click', function(event) {
    var cardTitle = event.target.closest(".card--title");
    if (cardTitle && this.contains(cardTitle)) {
      var newCard = document.createElement('p');
      newCard.className = 'card--title';
      newCard.innerText = 'Enter';
      document.body.appendChild(newCard);
    }
  });
}

myFunc();

使用Element#closest,如果您需要支持任何版本的 IE,则必须对其进行 polyfill;详情见链接。

还请注意,如果您想处理所有 .card--title 元素,即使它们位于您挂钩事件的容器的祖先中,也可以省略 &amp;&amp; this.contains(cardTitle) 部分。为了完整起见,我将其包含在内,但鉴于您将新的附加到 document.body,因此在此特定用例中您不需要它。

【讨论】:

  • 这个问题让我没有想到重复,但我认为 Xufox 和 Zakaria 可能是对的。无法删除;把它变成了 CW。
猜你喜欢
  • 2015-07-26
  • 2018-04-13
  • 2011-02-11
  • 2011-08-15
  • 2021-12-02
  • 2020-05-10
  • 2017-03-06
  • 2020-10-14
  • 1970-01-01
相关资源
最近更新 更多