【问题标题】:Attaching eventListener to dynamic elements in Javascript将 eventListener 附加到 Javascript 中的动态元素
【发布时间】:2014-10-31 03:27:49
【问题描述】:

我正在制作一个待办事项列表,并且在添加新列表项时动态添加了 li 和 button 标签。该按钮是一个 x 应该删除列表项。我尝试了几件事,但不知道如何为每个单独的 x 按钮创建一个 eventListener 并在单击时删除相应的列表项。

renderTodos 函数用于创建所有动态添加的内容。我为每个按钮设置了一个数据索引,我试图在其中访问每个按钮以在每个动态按钮上附加一个eventListener,但我不确定如何实现它。根据我的阅读,应该有一种方法可以使用currentTarget 或事件目标来执行此操作,但我不明白它是如何工作的。

var input = document.querySelector('input[name=todoItem]'),

btnAdd = document.querySelector('button[name=add]'),
btnClear = document.querySelector('button[name=clear]'),
list = document.querySelector('.todo'),
storeList = [];

function renderTodos(){
  var el = document.createElement('li'),
  x = document.createElement('button');
  listLength = storeList.length;
  
  //Set text for remove button
  x.innerHTML = 'x';

  for(var i = 0; i < listLength; i++){
    el.innerHTML = storeList[i];
    list.appendChild(el);
    x.setAttribute('data-index', i);
    el.appendChild(x);
  }

  // check for correct data-index property on x button
}

function addTodos(){
  storeList.push(input.value);

  // Check that input is getting pushed to list array
  console.log(storeList);
  renderTodos();
}


function clearList(){
  // make list empty
  list.innerHTML = '';
  storeList.splice(0, storeList.length);
  //render empty list
  renderTodos();
  
  //Check that list array is empty
  console.log(storeList);
}

btnAdd.addEventListener('click', addTodos);
btnClear.addEventListener('click', clearList);

到目前为止,列表中的所有其他内容都有效,我只是不知道如何实现这个eventListener

【问题讨论】:

  • renderTodos 只是在单击添加按钮时添加列表项和 x 按钮,这是它应该做的。我只需要弄清楚如何单击添加的 x 按钮以删除关联的列表项。
  • 我不太明白你的意思。当我查看开发工具并将多个项目添加到列表中时,它会显示每次单击添加按钮时都会创建一个列表项和按钮。每次我单击清除按钮时,它都会删除所有 li 和按钮。你的意思是没有新的元素被创造出来?抱歉,如果我遗漏了一些我不太了解的简单内容。
  • 我错过了list.appendChild(el);。它所做的是每次循环遍历 storeList 的所有成员,您看到的唯一一个就是最后一个。您不需要 for 循环,也不需要“渲染空列表”。长度为零的数组上的 for 循环什么也不做。

标签: javascript dom-events event-listener event-delegation


【解决方案1】:

一个简单的例子可以是

//a click hadler is added to #mylist which is already present in the dom
document.querySelector('#mylist').addEventListener('click', function(e) {
  //assuming that the the `x` is in a span and it is the only span in the `li` we check for that, we can improve this check more to make sure we have actually clicked on the delete button
  if (e.target.tagName == 'SPAN') {
    //if so then since we know the structure we can delete the parent node of the target which is the span element
    e.target.parentNode.parentNode.removeChild(e.target.parentNode);
  }
}, false);

//kindly forgive the use of jQuery here
for (var i = 0; i < 10; i++) {
  $('<li />', {
    text: i
  }).append('<span class="x">X</span>').appendTo('#mylist');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="mylist"></ul>

这是事件委托的一个非常基本的实现,其中实际事件被绑定到一个祖先元素,然后我们使用实际事件目标来确定是否对其采取行动。我们可以改进if 条件来测试一个类的任何其他属性!!!

【讨论】:

  • 谢谢你,这是我一直在寻找的帮助!只是给我一个类似的例子,而不是一行一行地为我解决我自己的问题。非常感谢。
【解决方案2】:

您可以使用以下方式为每个按钮添加侦听器:

 x.innerHTML = '';
 x.onclick = function(){
   var node = this.parentNode;
   node.parentNode.removeChild(node);
 };

或者您可以保持 renderTodos 代码原样并将删除委托给父 UL:

// Add the listener
list.addEventListener('click', removeItem);

// The listener function
function removeItem(event) {
  var node = event.target;

  // Check that the click came from an X button
  // better to check against a class name though
  if (node.tagName &&
      node.tagName.toLowerCase() == 'button' &&
      node.innerHTML == 'x') {
    node = node.parentNode;
    node.parentNode.removeChild(node);
  }
}

【讨论】:

  • 谢谢,这很有帮助。我可能会改变一些东西,比如你提到的按钮类,并尝试一些东西,但这可以正常工作。
【解决方案3】:

基本上你想要做的是在父容器上添加一个事件并等待事件冒泡并确定事件是否来自你的 x 标记,如果它是然后触发回调函数。这是我认为大多数图书馆都使用的概念..

或者使用jQuery之类的库,为什么要解决别人已经解决的问题。

【讨论】:

  • 这个网站上的一切都归结为使用 jquery。为什么要在这么小的东西上使用 jquery?为一些相对简单的事情添加整个库似乎没有必要。这个项目的重点是我试图学习和理解 javascripts 本身的事件。如果我不能用普通的 javascript 来做,我永远不会明白 jquery 到底在做什么。
  • 感谢您对父容器的解释,它确实有点帮助。我有一个想法,我需要这样做,但我不知道该怎么做。
  • 你明白什么是OR吗!!!你为什么不实施它!我没有看到你的尝试......你想让我们用勺子喂你遇到的每一个问题吗?
  • 涉及的复杂性如此之多,以至于很难做到正确(适用于所有浏览器、控件),这就是为什么人们使用/推荐久经考验的解决方案而不是每次都推出本土解决方案的原因。看起来人们正忙于保存 28kb 的数据,但不介意使用 document.addEventListener 等 JavaScript 代码
  • 是的,我知道或是什么。您不必提供帮助,很抱歉,如果您觉得有义务回答这里的每一个问题,以获得更高的声誉并作为程序员对自己感觉良好。我是新手,很多东西还不懂。我认为这就是这个网站的目的。正如问题中所述,我已经尝试以各种方式实现这一点,但我所拥有的一切都不是很接近或看起来正确,所以如果它只是会让它更难阅读并查看问题所在,为什么要发布它。我不想逐行说明答案,只是想知道如何使用目标。
猜你喜欢
  • 2015-11-25
  • 2020-08-11
  • 2014-10-05
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多