如何将eventListener应用于具有相同类的多个元素并使每个元素独立响应

时间:2019-03-02 18:33:35

标签: javascript dom addeventlistener

我的HTML中有一个元素列表,如下所示:

<div class='container'>
    <div class="zone green"></div>
    <div class="zone red"></div>
    <div class="zone blue"></div>
    <div class="zone yellow"></div>
    <div class="zone purple"></div>
    <div class="zone brown"></div>
    <div class="zone green"></div>
    <div class="zone red"></div>
    <div class="zone blue"></div>
    <div class="zone yellow"></div>
    <div class="zone purple"></div>
    <div class="zone brown"></div>
    <script type="text/javascript" src="script.js"></script>
  </div>

我试图做到这一点,以使我单击的每个元素都可以将元素中的动物记录到控制台。这是我的尝试:

const selection = document.querySelectorAll(".zone");


selection.forEach(element => {
    element.addEventListener('click', pickSelection(element))
})


function pickSelection(animal) {
    console.log(animal.textContent)
}

但是当我单击任何元素时,它什么都没有返回。但是,一旦将eventListener更改为此,它便开始工作:

selection.forEach(element => {
    element.addEventListener('click', () => pickSelection(element))
})

为什么它在第二版代码而不是第一版中起作用?在第一个版本中,我以为我是通过编写“ pickSelection(element)”将元素参数传递给pickSelection函数的,但是显然只有在其前面有“()=>”的情况下它才有效,但是有什么区别用这种表示法?谢谢。

3 个答案:

答案 0 :(得分:1)

在第一个版本中,您正在执行pickSelection函数而不是传递其引用, addEventListener 期望当特定事件为触发。

但是由于您传递了pickSelection函数的返回值undefined(因为您没有从pickSelection返回任何内容,所以默认情况下它返回的是undefined)它不起作用。

在第二个版本中,您实际上是将函数引用传递给addEventListner,这是箭头函数语法。

通过简单地传递引用pickSelection,下面的内容也可以工作,但是这次它将收到 event 对象。

const selection = document.querySelectorAll(".zone");
selection.forEach(element => {
   element.addEventListener('click', pickSelection)
})
function pickSelection(event) {
      //getting the event object from the callback, target refers to the current element clicked.
    console.log(event.target.textContent)
}
<div class='container'>
    <div class="zone green"></div>
    <div class="zone red"></div>
    <div class="zone blue"></div>
    <div class="zone yellow"></div>
    <div class="zone purple"></div>
    <div class="zone brown"></div>
    <div class="zone green"></div>
    <div class="zone red"></div>
    <div class="zone blue"></div>
    <div class="zone yellow"></div>
    <div class="zone purple"></div>
    <div class="zone brown"></div>
</div>

答案 1 :(得分:0)

此行

element.addEventListener('click', pickSelection(element));

实际上是

const temp = pickSelection(element);
element.addEventListener('click', temp);

你想要的是

element.addEventListener('click', pickSelection);

您看到区别了吗?

在此版本中

element.addEventListener('click', pickSelection(element))

您调用了函数pickSelection并将其传递给element。然后将pickSelection返回element.addEventListener

您想要/需要做的就是将函数本身传递给element.addEventListener

此版本有效的原因

selection.forEach(element => {
    element.addEventListener('click', () => pickSelection(element))
})

是因为您要将匿名函数传递给element.addEventListener。这些行可以翻译成这个

function anonymousFn1(element) {
    function anonymousFn2() {
         pickSelection(element);
    }
    element.addEventListener('click', anonymousFn2);
}

selection.forEach(anonymousFn1);

请注意,在功能上还有另一个区别。

在这个

 element.addEventListener('click', pickSelection);

click事件将Event object传递给pickSelection,而在另一个事件中,变量element是在forEach称为anonmousFn1的情况下“封闭”的{{3 }},所以当调用anonymousFn2时,就使用了element变量。

所以要使第一个开始工作,您真的需要这个

function pickSelection(event) {
    const element = event.target;
    console.log(element.textContent);
}

示例:

const selection = document.querySelectorAll(".zone");

selection.forEach(element => {
    element.addEventListener('click', pickSelection);
});

function pickSelection(event) {
    element = event.target;
    console.log(element.textContent);
}
<div class='container'>
    <div class="zone green"></div>
    <div class="zone red"></div>
    <div class="zone blue"></div>
    <div class="zone yellow"></div>
    <div class="zone purple"></div>
    <div class="zone brown"></div>
    <div class="zone green"></div>
    <div class="zone red"></div>
    <div class="zone blue"></div>
    <div class="zone yellow"></div>
    <div class="zone purple"></div>
    <div class="zone brown"></div>
</div>

答案 2 :(得分:0)

旁注:在每个元素上注册一个侦听器是一种不良做法。改用事件委托:

document.querySelector(`.container`).addEventListener(`click`, ({target}) => {
  const el = target.closest(`.zone`);
  if (el) {
    console.log(el.textContent);
  }
})
<div class='container'>
  <div class="zone green"></div>
  <div class="zone red"></div>
  <div class="zone blue"></div>
  <div class="zone yellow"></div>
  <div class="zone purple"></div>
  <div class="zone brown"></div>
  <div class="zone green"></div>
  <div class="zone red"></div>
  <div class="zone blue"></div>
  <div class="zone yellow"></div>
  <div class="zone purple"></div>
  <div class="zone brown"></div>
</div>