jQuery: funkcja klikania wyklucz dzieci.


144

Próbuję owinąć głowę wokół funkcji jQuery „.not ()” i napotykam problem. Chciałbym, aby nadrzędny element DIV był „klikalny”, ale jeśli użytkownik kliknie element podrzędny, skrypt nie zostanie wywołany.

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

html:

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

Odpowiedzi:


198

Aby to zrobić, zatrzymaj kliknięcie dziecka za pomocą .stopPropagation :

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

Zapobiegnie to wzrostowi kliknięć dziecka powyżej ich poziomu, aby rodzic nie otrzymał kliknięcia.

.not() jest używany nieco inaczej, filtruje elementy poza twój selektor, na przykład:

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

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

Jeśli chodzi o kliknięcie, Twoim problemem jest to, że kliknięcie dziecka przenosi się do rodzica , a nie to, że nieumyślnie dołączyłeś do niego moduł obsługi kliknięcia.


dzięki nick, nie sądzę, że tego właśnie szukałem. Przykro mi, że nie wyraziłem się jasno w moim pytaniu. Chcę, aby cały div.example zniknął, tylko po kliknięciu elementu nadrzędnego, a nie po kliknięciu podrzędnego elementu div. Powodem tego jest to, że chciałbym, aby użytkownik mógł kliknąć tekst akapitu i nie powodować zanikania tekstu. Jeśli użytkownik kliknie zewnętrzny element div (nadrzędny element div), wszystko zniknie.
— superUntitled

@superUntitled - Dzięki za wyjaśnienie ... odpowiedź została zaktualizowana, aby to zrobić, spróbuj.
— Nick Craver

18
@Asaf - użyj e.stopPropagation();zamiast w return false;tym przypadku.
— Nick Craver

2
Możesz także użyć }).find('.classes-to-ignore').click(function(e) {do wybrania określonych elementów podrzędnych
— Paul Mason,

5
Nie rozumiem, dlaczego mówisz mu, żeby użył, e.stopPropagation()a potem użył return falsezamiast tego. return falsejest równoważne, e.preventDefault(); e.stopPropagation()więc może mieć nieoczekiwane skutki uboczne.
— Steen Schütt

183

Używam następujących znaczników i napotkałem ten sam problem:

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

Tutaj użyłem następującej logiki:

$(".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");
});

Jeśli chodzi o dokładne pytanie, widzę, że działa w następujący sposób:

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

lub oczywiście na odwrót:

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

Mam nadzieję, że to pomoże.


28
Myślę, że to lepsze rozwiązanie. W żaden sposób nie przeszkadza dzieciom i powinien działać lepiej, ponieważ potencjalnie nie rejestruje tysięcy oddzwonień, jeśli są tysiące dzieci.
— LucasB

4
@ l2aelba - powinieneś używać .on("click", ...)w najnowszych wersjach jQuery, ponieważ .live()jest ono przestarzałe od wersji 1.7. Zobacz api.jquery.com/live
— Chris,

Tak, @Chris wysłałem 16 listopada '12 o 10:12
— l2aelba,

Przepraszamy, prawdopodobnie nie musiałem odnosić się do twojego identyfikatora. Dodałem komentarz w dużej mierze dla każdego, kto czytał tę odpowiedź.
— Chris,

1
Ta odpowiedź jest lepsza niż zaakceptowana odpowiedź, ponieważ nie przerywa żadnych kliknięć elementów podrzędnych
— cameronjonesweb

24

Możesz też:

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

   // ... //
});

Musisz zwrócić false, aby uniknąć zdarzenia kliknięcia w elementach podrzędnych. Rewizja była błędna
— dani24

6

Moje rozwiązanie:

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

Podobne do rozwiązania powyżej twojego.
— user460114

3

Osobiście dodałbym moduł obsługi kliknięcia do elementu podrzędnego, który nic nie robił, ale zatrzymywał propagację kliknięcia. Więc wyglądałoby to mniej więcej tak:

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

Jaka jest różnica między stopPropagationi zwracaniem fałszu, jak sugerują inne odpowiedzi?
— Crashalot

Wierzę, że w tym przypadku funkcjonowałyby tak samo, ale myślę, że zatrzymanie propagacji jest bardziej zrozumiałe dla celu tego, co się dzieje, i pozostawia większą szansę na zrozumienie, dlaczego robi się to później. Ale to dyskusyjne.
— Noahone

Dziękuję za wyjaśnienie. wygląda na to, że stopPropagationmoże być czystszy, ponieważ nie powstrzyma zdarzeń na elementach podrzędnych, co może się zdarzyć w przypadku return false.
— Crashalot

0

Oto przykład. Zielony kwadrat to element nadrzędny, a żółty to element podrzędny.

Mam nadzieję, że to pomoże.

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>

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.