如何根据class通过addEventListener获取当前元素?

How to retrieve the current element with addEventListener based on class?

我正在使用一个函数来检索接收事件的当前元素(在本例中为单击),但我想从我的 HTML 脚本中删除该函数并使用 event listener 做同样的事情,但是我使用 class 来瞄准元素。如果我只有一个元素,那会很容易,但事实并非如此。

我的第一个想法是使用 querySelector,但它只给了我第一个元素,这是应该的。 我可以使用 querySelectorAll,但在那种情况下,我相信我需要一个 index 或类似的东西,这意味着一个循环,因此,HTML 脚本中的一个函数,它是正是我在这个风景中试图避免的。

简而言之,如果我点击第一个元素我想要检索它,如果我点击第二个我想要第二个等等,但我想在同一个 event listener.

有简单的方法吗?

P.S。我不想使用 ID。

//This is what I'm doing:
function getElement() {
  const element = event.currentTarget
  
  console.log(element)
}

//This is what I want to do:
/*
const elements = document.querySelector('.class-example')

elements.addEventListener('click', (e) => console.log(e.currentTarget))
*/
.class-example {
  cursor: pointer;
  margin-bottom: 10px;
}

.class-example:first-of-type {
  background-color: red;
}

.class-example:nth-of-type(2) {
  background-color: yellow;
}

.class-example:nth-of-type(3) {
  background-color: green;
}

.class-example:nth-of-type(4) {
  background-color: blue;
  color: white;
}
<div onClick="getElement()" class="class-example" >Div 1</div>
<div onClick="getElement()" class="class-example" >Div 2</div>
<div onClick="getElement()" class="class-example" >Div 3</div>
<div onClick="getElement()" class="class-example" >Div 4</div>

Afaik,不可能同时在多个元素上放置一个事件侦听器,除非您遍历它们并在每个元素上附加一个。但是,您可以简单地在整个文档上放置一个事件侦听器,然后只匹配您需要的内容:

document.addEventListener('click',function(e){
    if(e.target && e.target.classList.contains('class-example')){
        //do something
    }
});

这还有一个额外的好处,即它也适用于动态添加的元素。

编辑(感谢 Mitya):这称为事件委托。如果您对这方面的更多信息感兴趣,Mitya provides a guide here.

有两种可能的方法...

...一个人要么将每个元素订阅到一个人希望收到通知并想要处理的事件...

function getExampleNode(evt) {
  const elmNode = evt.currentTarget;
 
  console.log(elmNode);

  return elmNode;
}

function mainInit() {
  document
    .querySelectorAll('.class-example')
    .forEach(elmNode =>
      elmNode.addEventListener('click', getExampleNode)
    );
}
mainInit();
.class-example {
  cursor: pointer;
  margin-bottom: 5px;
}
.class-example:first-of-type {
  background-color: red;
}
.class-example:nth-of-type(2) {
  background-color: yellow;
}
.class-example:nth-of-type(3) {
  background-color: green;
}
.class-example:nth-of-type(4) {
  background-color: blue;
  color: white;
}

.as-console-wrapper { max-height: 50%!important; }
<div class="container">
  <div class="A class-example">
    <span>within ...
      <span>div 1</span>
    </span>
  </div>
  <div class="B class-example">
    <span>within ...
      <span>div 2</span>
    </span>
  </div>
  <div class="C class-example">
    <span>within ...
      <span>div 3</span>
    </span>
  </div>
  <div class="D class-example">
    <span>within ...
      <span>div 4</span>
    </span>
  </div>
</div>

...或者使用事件委托,其中只为这个事件订阅一个分组元素。

function getExampleNode(evt) {
  const containerNode = evt.currentTarget;
  const targetNode = evt.target; // either <span/> or <div/>

  let exampleNode;
  let isInExample;

  Array.from(
    document.querySelectorAll('.class-example')
  ).some(elmNode => {
    isInExample = (elmNode === targetNode) || elmNode.contains(targetNode);
    if (isInExample) {

      exampleNode = elmNode;
    }
    return isInExample;
  });

  console.log('targetNode :', targetNode);
  console.log('exampleNode :', exampleNode);
  console.log('\n');

  return exampleNode;
}

function mainInit() {
  document
    .querySelector('.container')
    .addEventListener('click', getExampleNode);
}
mainInit();
.class-example {
  cursor: pointer;
  margin-bottom: 5px;
}
.class-example:first-of-type {
  background-color: red;
}
.class-example:nth-of-type(2) {
  background-color: yellow;
}
.class-example:nth-of-type(3) {
  background-color: green;
}
.class-example:nth-of-type(4) {
  background-color: blue;
  color: white;
}

.as-console-wrapper { max-height: 50%!important; }
<div class="container">
  <div class="A class-example">
    <span>within ...
      <span>div 1</span>
    </span>
  </div>
  <div class="B class-example">
    <span>within ...
      <span>div 2</span>
    </span>
  </div>
  <div class="C class-example">
    <span>within ...
      <span>div 3</span>
    </span>
  </div>
  <div class="D class-example">
    <span>within ...
      <span>div 4</span>
    </span>
  </div>
</div>

第一种方法的优点是它的事件处理简单,因为人们总是可以确定事件的 currentTarget 等于订阅事件的元素之一。

首先创建的事件侦听器的数量较少,但如果必须处理稍后添加到 DOM 的元素,可能会丢失处理信息。 .

第二种方法涵盖了后一种情况。这里的事件注册要简单的多,但是事件处理器的实现要复杂一点。

必须提供额外的逻辑,通过确定可能的元素中哪些确实包含或等于事件的 currentTarget.

来搜索所需的元素