jQuery:单击功能排除子级。


144

试图绕过jQuery“ .not()”函数,遇到一个问题。我希望父div是“可单击的”,但是如果用户单击子元素,则不会调用该脚本。

$(this).not(children()).click(function(){
   $(".example").fadeOut("fast");
});

HTML:

<div class="example">
   <div>
      <p>This content is not affected by clicks.</p>
   </div>
</div>

Answers:


198

为此,请使用.stopPropagation停止对子级的点击:

$(".example").click(function(){
  $(this).fadeOut("fast");
}).children().click(function(e) {
  return false;
});

这样可以阻止孩子的点击次数超过其水平,从而使父级不会收到该点击。

.not() 用法有所不同,它从选择器中过滤出元素,例如:

<div class="bob" id="myID"></div>
<div class="bob"></div>

$(".bob").not("#myID"); //removes the element with myID

对于单击而言,您的问题是,对子项点击会上升到父项,而不是您无意中将了点击处理程序附加到了子项上。


谢谢尼克,我不认为这是我想要的。对不起,我不清楚我的问题。我希望整个div.example仅当单击父元素时才淡出,而不是在单击子div时淡出。这样做的原因是我希望用户能够单击段落文本而没有文本fadeOut。如果用户单击外部div(父div),则所有内容都会淡出。
superUntitled 2010年

@superUntitled-感谢您的澄清...答案已更新为执行此操作,请尝试一下。
尼克·克雷弗

18
@Asaf- 在这种情况下使用e.stopPropagation();代替return false;
尼克·克雷弗

2
您还可以}).find('.classes-to-ignore').click(function(e) {用来选择特定的子元素
Paul Mason

5
我不明白您为什么告诉他先使用e.stopPropagation()然后再使用return falsereturn false等价于此,e.preventDefault(); e.stopPropagation()因此可能会有意想不到的副作用。
SteenSchütt2015年

183

我正在使用以下标记,并且遇到了同样的问题:

<ul class="nav">
    <li><a href="abc.html">abc</a></li>
    <li><a href="def.html">def</a></li>
</ul>

在这里,我使用了以下逻辑:

$(".nav > li").click(function(e){
    if(e.target != this) return; // only continue if the target itself has been clicked
    // this section only processes if the .nav > li itself is clicked.
    alert("you clicked .nav > li, but not it's children");
});

关于确切的问题,我可以看到它的工作方式如下:

$(".example").click(function(e){
   if(e.target != this) return; // only continue if the target itself has been clicked
   $(".example").fadeOut("fast");
});

或者当然也可以:

$(".example").click(function(e){
   if(e.target == this){ // only if the target itself has been clicked
       $(".example").fadeOut("fast");
   }
});

希望有帮助。


28
我认为这是更好的解决方案。它不会以任何方式干扰子级,并且应该有更好的性能,因为如果有成千上万的子级,它不会潜在地注册数千个回调。
LucasB 2012年

4
@ l2aelba-从v1.7 开始不推荐使用.on("click", ...)jQuery的最新版本.live()。参见api.jquery.com/live-
克里斯,克里斯,

是的,@ Chris I发布于2012年11月16日10:12
l2aelba

抱歉,可能不需要引用您的ID。我为大多数阅读此答案的人添加了评论。
克里斯,

1
此答案比公认的答案更好,因为它不会中断子元素上的任何点击事件
cameronjonesweb

24

或者,您也可以:

$('.example').on('click', function(e) { 
   if( e.target != this ) 
       return false;

   // ... //
});

您必须返回false,以避免children元素中的click事件。修改是错误的
dani24 '16

6

我的解决方案:

jQuery('.foo').on('click',function(event){
    if ( !jQuery(event.target).is('.foo *') ) {
        // code goes here
    } 
});

类似于您上面的解决方案。
user460114 '18

3

我个人会向子元素添加一个点击处理程序,该操作除了停止点击的传播外什么也没有做。因此,它看起来像:

$('.example > div').click(function (e) {
    e.stopPropagation();
});

stopPropagation和其他答案一样,返回false和有什么区别?
Crashalot

我相信在这种情况下,它们的功能相同,但是我认为停止传播对于正在执行的目的更加清楚,并且为以后理解为什么会进行提供了更好的机会。但这值得商de。
Noahone

感谢您的澄清。似乎stopPropagation更干净,因为它不会阻止发生在上的子元素上的事件return false
Crashalot

0

这是一个例子。绿色正方形是父元素,黄色正方形是子元素。

希望这会有所帮助。

var childElementClicked;

$("#parentElement").click(function(){

		$("#childElement").click(function(){
		   childElementClicked = true;
		});

		if( childElementClicked != true ) {

			// It is clicked on parent but not on child.
      // Now do some action that you want.
      alert('Clicked on parent');
			
		}else{
      alert('Clicked on child');
    }
    
    childElementClicked = false;
	
});
#parentElement{
width:200px;
height:200px;
background-color:green;
position:relative;
}

#childElement{
margin-top:50px;
margin-left:50px;
width:100px;
height:100px;
background-color:yellow;
position:absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="parentElement">
  <div id="childElement">
  </div>
</div>

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.