JS点击事件和“此”项目

时间:2018-11-26 12:32:17

标签: javascript

我真的是Vanilla JS的新手,所以有点困惑。

假设我具有以下html结构:

<div class="play-animation"></div>
<div class="play-animation"></div>
<div class="play-animation"></div>
<div class="play-animation"></div>
<div class="play-animation"></div>

我有这段代码可以检查是否单击了其中一项:

document.addEventListener('click', function(item) {

  if(item.target.matches('.play-animation')) {

    console.log(item);
  }
})

它并没有console.log我点击过的元素。我知道为什么它不能控制它,但是我不知道如何重建代码,所以它将成为我单击的console.log项。

非常感谢您的提前帮助!

3 个答案:

答案 0 :(得分:1)

有很多解决方案可以将事件绑定到元素。带有javascript和DOM事件的代码就像:

document.querySelectorAll('.play-animation').forEach(function (item) {
  item.addEventListener('click', function(){
      console.log(this);
  })
})
div{
  border:1px solid red;
  padding:4px;
}
<div class="play-animation">1</div>
<div class="play-animation">2</div>
<div class="play-animation">3</div>
<div class="play-animation">4</div>
<div class="play-animation">5</div>

更新:
正如评论中提到的Quentin和下一个帖子中回答的t-j-crowder一样,并且根据描述事件委托的优势的this article,我添加了以下部分来改善答案:< / p>

document.querySelector('.container').addEventListener('click', function (event) {
    if (event.target.matches('.item')) {
        console.log('item clicked')
    } else {
        console.log('I am a', event.target.nodeName, ' not `item`');
    }
})

setTimeout(function () {
    var newItem = document.createElement('div');
    newItem.innerText = "I added 3 seconds later. but I have event too!";
    newItem.className = 'item';
    document.querySelector('.container').appendChild(newItem)
}, 3000)
.container .item,
.container .not-item {
    border: 1px solid red;
    padding: 5px;
}
<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="not-item">4</div>
</div>

好吧,在以上片段中,您可以通过在某些元素的父元素上添加事件来看到子元素也将具有该事件。而且事件委托是实时的,这意味着以后,通过将一些子代添加到父代,新子代也将拥有该事件,并且无需将该事件绑定到新子代。
jQuery库中也可以通过以下方法使用on,如下所示:

$('.container').on('click','.item',function(){
    // item clicked, no matter when item is added to the container.
})

P.S:
还有this link

matches方法的浏览器兼容性

答案 1 :(得分:1)

target是被单击的元素。在您引用的HTML中,假设有一些CSS使这些div的高度不为零(因为它们将没有内容),因为您的{{1中没有后代元素,所以这将一直是您要检查的元素}},但是从您的问题中我怀疑您有未显示的后代元素,例如:

div

如果用户单击上面的<div class="play-animation">Some <span>styled</span> text</div> <div class="play-animation"><img src="2.png"></div> span,则代码中的imgitem.target的确应为itemevent)将会是espan,而不是img

要确定点击是否通过了div,请结合使用Element#closestNode#contains

div
document.addEventListener('click', function(event) {
    var div = event.target.closest(".play-animation");
    if (div && this.contains(div)) {
        console.log("Click passed through .play-animation");
    } else {
        console.log("Click didn't pass through .play-animation");
    }
});

现在,由于您将事件挂在<div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <span>text in span but not in a .play-animation div</span>上,因此实际上不需要document调用:

contains
document.addEventListener('click', function(event) {
    var div = event.target.closest(".play-animation");
    if (div) {
        console.log("Click passed through .play-animation");
    } else {
        console.log("Click didn't pass through .play-animation");
    }
});

但是,如果将事件挂在<div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <div class="play-animation"><span>text in span</span></div> <span>text in span but not in a .play-animation div</span>以外的任何事物上(或者可能是documentdocument以外的任何事物上,则可以)。


如果由于某种原因,您必须支持没有document.body的过时浏览器,则可以自己处理循环以进行检查,这也就意味着您不需要{{1} }致电,因为您可以将签到折起:

Element#closest

答案 2 :(得分:-3)

正确的方法是将侦听器直接绑定到DOM节点,而不是侦听任何单击并匹配类名的事件。

检查此:JavaScript click event listener on class