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.