如何使点击事件仅在父级DIV而非子级上触发?


211

我有一个带有foobarclassed的DIV,并且该DIV中有一些未分类的DIV,但是我想它们正在继承foobar该类:

$('.foobar').on('click', function() { /*...do stuff...*/ });

我希望仅在单击DIV中的某个位置而不在其子DIV上单击时才会触发。

Answers:


439

如果e.target元素与相同this,则您没有单击后代。

$('.foobar').on('click', function(e) {
  if (e.target !== this)
    return;
  
  alert( 'clicked the foobar' );
});
.foobar {
  padding: 20px; background: yellow;
}
span {
  background: blue; color: white; padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='foobar'> .foobar (alert) 
  <span>child (no alert)</span>
</div>


该答案解释了评论
gdoron支持Monica 2012年

@gdoron:亚当太仁慈了。:)

1
嗨@vicky 仅供参考,JavaScript具有两种不同的值相等比较。的===!==用途“严格相等比较算法”,而==!=用途“抽象相等比较算法”,它的类型的矫顽。一般的智慧是始终使用严格的比较,除非特别需要强制类型(因为其规则有些复杂)。在这种情况下,因为正在比较对象,所以实际上并没有什么不同,但是您会发现大多数人仍然会坚持严格的比较。

1
@vicky:没关系。仍然是正确的。只是让JS具有不同的运算符。;-)

3
这是一个很好的答案,因为它也可以与Vanilla JS addEventListener一起使用,并且不特定于jQuery。
Michael Giovanni Pumo

64

如果您不介意仅针对较新的浏览器,则还有另一种可行的方法。只需添加CSS

pointer-events: none;

您想要捕获点击的div的所有子级。这是支持表

http://caniuse.com/#feat=pointer-events


13
知道我应该避免写“谢谢”评论,但是我可以为此而亲吻你:-)
Simona Adriani

@SimonaAdriani是吗?
n3wb '18

谢谢,我以同样的方式做,但是我正在努力围绕它编写单元测试用例。如何确定click应该阻止程序化点击事件触发器?
Pankaj Parkar

29

您可以使用冒泡方式:

$('.foobar').on('click', function(e) {
    // do your thing.
}).on('click', 'div', function(e) {
    // clicked on descendant div
    e.stopPropagation();
});

对于我的特定情况,这似乎是一个不错的解决方案,因为我只想排除对后代<a>元素的点击。有一个问题:当我单击它们时,该事件仍然会触发(在Google Chrome中测试)。有这样的变体也可以防止这种情况吗?
cgogolin


28

我没有得到公认的工作答案,但这似乎可以解决问题,至少在香草JS中是如此。

if(e.target !== e.currentTarget) return;

1
e.currentTarget比引用更准确,this因为this指向的对象可以根据调用对象的范围和上下文而变化
eballeste

20
//bind `click` event handler to the `.foobar` element(s) to do work,
//then find the children of all the `.foobar` element(s)
//and bind a `click` event handler to them that stops the propagation of the event
$('.foobar').on('click', function () { ... }).children().on('click', function (event) {
    event.stopPropagation();
    //you can also use `return false;` which is the same as `event.preventDefault()` and `event.stopPropagation()` all in one (in a jQuery event handler)
});

这将停止click事件在该元素的任何子元素上的传播(冒泡),.foobar因此该事件不会到达该.foobar元素以触发其事件处理程序。

这是一个演示:http : //jsfiddle.net/bQQJP/


3
$(".advanced ul li").live('click',function(e){
    if(e.target != this) return;
    //code
    // this code will execute only when you click to li and not to a child
})

2

我遇到了同样的问题,并提出了这个解决方案(基于其他答案)

 $( ".newsletter_background" ).click(function(e) {
    if (e.target == this) {
        $(".newsletter_background").hide();
    } 
});

基本上它说如果目标是div然后运行代码,否则什么也不做(不要隐藏它)


1

我的情况与此类似,但是这种情况下您的foobar-s 很少,而您每次单击只希望关闭一个-s:

寻找父案

$(".foobar-close-button-class").on("click", function () {
    $(this).parents('.foobar').fadeOut( 100 );
    // 'this' - means that you finding some parent class from '.foobar-close-button-class'
    // '.parents' -means that you finding parent class with name '.foobar'
});

查找儿童案

$(".foobar-close-button-class").on("click", function () {
    $(this).child('.foobar-close-button-child-class').fadeOut( 100 );
    // 'this' - means that you finding some child class from '.foobar-close-button-class'
    // '.child' -means that you finding child class with name '.foobar-close-button-child-class'
});

1

您可以使用event.currentTarget。它只会做点击事件,而不会得到事件。

target = e => {
    console.log(e.currentTarget);
  };
<ul onClick={target} className="folder">
      <li>
        <p>
          <i className="fas fa-folder" />
        </p>
      </li>
    </ul>


1

如果您无法使用pointer-events: none;并定位到现代浏览器,则可以使用以下方法composedPath来检测对对象的直接点击:

element.addEventListener("click", function (ev) {
    if (ev.composedPath()[0] === this) {
        // your code here ...
    }
})

您可以在此处阅读有关composedPath的更多信息:https : //developer.mozilla.org/en-US/docs/Web/API/Event/composedPath


0

// if its li get value 
document.getElementById('li').addEventListener("click", function(e) {
                if (e.target == this) {
                    UodateNote(e.target.id);
                }
                })
                
                
                function UodateNote(e) {

    let nt_id = document.createElement("div");
    // append container to duc.
    document.body.appendChild(nt_id);
    nt_id.id = "hi";
    // get conatiner value . 
    nt_id.innerHTML = e;
    // body...
    console.log(e);

}
li{
 cursor: pointer;
    font-weight: bold;
  font-size: 20px;
    position: relative;
    width: 380px;
    height: 80px;
    background-color: silver;
    justify-content: center;
    align-items: center;
    text-align: center;
    margin-top: 0.5cm;
    border: 2px solid purple;
    border-radius: 12%;}
    
    p{
     cursor: text;
  font-size: 16px;
   font-weight: normal;
    display: block;
    max-width: 370px;
    max-height: 40px;
    overflow-x: hidden;}
<li id="li"><p>hi</p></li>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.