将事件侦听器添加到将来的项目(无需jQuery)

将事件侦听器添加到将来的项目(无需jQuery)

问题描述:

很好奇我是否有能力用Vanilla JS编写列表应用程序.问题是事件侦听器未添加到新列表项中.

Curious if I was up to challenge of writing something a list app with Vanilla JS. Problem is event listener is not being added to new list items.

我将删除按钮添加到列表中的现有项目:

I add a delete button to existing items in the list:

const deleteButton = document.querySelectorAll('span');
deleteButton.forEach(button => button.addEventListener('click', deleteItem));

我想为新项目添加一个删除按钮.

I want to add a delete button for new items.

我知道jQuery的 on()方法将为动态创建的事件添加一个侦听器-Vanilla JS中是否有等效项?

I know jQuery's on() method will add a listener for dynamically created events — is there an equivalent in Vanilla JS?

jQuery不会为动态创建的元素添加侦听器.它的作用是具有可以为您设置事件委托的语法.

jQuery doesn't add listeners for dynamically created elements. What it does is it has a syntax that will set up event delegation for you.

您可以通过侦听某些容器元素并检查单击了哪些内容以查看处理程序是否应该运行来进行相同的操作.

You can do the same by listening on some container element and checking what was clicked to see if the handler should run.

例如,尽管建议使用更本地的容器,但它会监听 body .

For example, this listens on the body, though a more local container is advisable.

document.body.addEventListener("click", function(event) {
  if (event.target.matches("span")) {
    deleteItem.call(this, event);
  }
});

这是一个有限的实现,因为它仅检查 event.target 以查看其是否与选择器匹配.为了更全面,您需要遍历 event.target .parentNode s,并逐一检查,直到到达 this元素.

This is a limited implementation as it only checks the event.target to see if it matches the selector. To be more thorough, you'd want to traverse from the event.target up through its .parentNodes, and check each one until you get to the this element.

可以很容易地将其抽象为构建处理程序的辅助函数.

This can be easily abstracted out to a helper function that builds your handler.

document.body.addEventListener("click", delegate("span", deleteItem));

function deleteItem(event) {
  console.log("clicked on '%s'", this.textContent);
}

function delegate(selector, handler) {
  return function(event) {
    var targ = event.target;
    do {
      if (targ.matches(selector)) {
        handler.call(targ, event);
      }
    } while ((targ = targ.parentNode) && targ != event.currentTarget);
  }
}

span { color: red; }

<div>
  <span>I'm a span!</span>
  Not a span
  <p>
    <span>Another span!</span>
  </p>
</div>