jQuery: функція клацання виключає дітей.


144

Намагаюся обернути голову навколо функції jQuery ".not ()" і зіткнувся з проблемою. Я хотів би, щоб батьківський дів був "клікабельним", але якщо користувач натискає на дочірній елемент, сценарій не викликається.

$(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

@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()це було застаріло з версії 1.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;

   // ... //
});

Ви повинні повернути помилкове значення, щоб уникнути події клацання в елементах дітей. Ревізія була помилковою
dani24

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.