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>

Ответы:


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 был fadeOut, только при щелчке по родительскому элементу, а не при щелчке по дочернему элементу. Причина этого в том, что я хотел бы, чтобы пользователь мог щелкнуть текст абзаца и не иметь текст fadeOut. Если пользователь нажимает на внешний div (родительский div), то все исчезнет.
— названия

@superUntitled - Спасибо за разъяснения ... ответ обновлен, чтобы сделать это, попробуйте.
— Ник Крейвер

18
@Asaf - использовать e.stopPropagation();вместо return false;этого.
— Ник Крейвер

2
Вы также можете использовать, }).find('.classes-to-ignore').click(function(e) {чтобы выбрать определенные дочерние элементы
— Пол Мейсон

5
Я не понимаю, почему вы говорите ему использовать, e.stopPropagation()а затем использовать return falseвместо этого. return falseэквивалентно, e.preventDefault(); e.stopPropagation()поэтому у него могут быть неожиданные побочные эффекты.
— Стин Шютт,

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

4
@ l2aelba - вы должны использовать .on("click", ...)в последних версиях jQuery .live(), что устарело с v1.7. См. Api.jquery.com/live
— Крис

Да, @Chris я отправил 16 ноября '12 в 10:12
— l2aelba

Извините, вероятно, не нужно указывать ваш идентификатор. Я добавил комментарий в основном для тех, кто читает этот ответ.
— Крис

1
Этот ответ лучше принятого, так как он не прерывает события щелчка на дочерних элементах
— cameronjonesweb

24

Или вы можете сделать также:

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

   // ... //
});

Вы должны вернуть false, чтобы избежать события click в дочерних элементах.
— Редакция

6

Мое решение:

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

Похоже на решение выше вашего.
— user460114

3

Лично я бы добавил обработчик кликов к дочернему элементу, который ничего не делал, кроме как остановил распространение клика. Так это будет выглядеть примерно так:

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

В чем разница между stopPropagationвозвратом ложных, как предлагают другие ответы?
— Crashalot

Я полагаю, что в этом случае они будут работать одинаково, но я думаю, что прекращение распространения более понятно для целей того, что делается, и оставляет больше шансов понять, почему это делается позже. Но это спорно.
— Ноахоне

Спасибо за разъяснения. Кажется, что он 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>

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.