jQuery: la funzione clic esclude i bambini.


144

Sto cercando di avvolgere la mia testa attorno alla funzione j .Query ".not ()", e ho riscontrato un problema. Vorrei che il div genitore fosse "cliccabile" ma se un utente fa clic su un elemento figlio, lo script non viene chiamato.

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

l'html:

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

Risposte:


198

Per fare ciò, interrompere il clic sul figlio utilizzando .stopPropagation :

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

Ciò impedirà ai clic secondari di gorgogliare oltre il loro livello in modo che il genitore non riceva il clic.

.not() viene usato in modo leggermente diverso, filtra gli elementi dal selettore, ad esempio:

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

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

Per fare clic, il tuo problema è che il clic su un bambino si gonfia al genitore , non che tu abbia inavvertitamente attaccato un gestore di clic al figlio.


grazie nick, non penso che sia quello che stavo cercando. Mi dispiace di non essere stato chiaro nella mia domanda. Voglio che l'intero div.example svanisca, solo quando si fa clic sull'elemento genitore, non quando si fa clic sul div figlio. La ragione di ciò è che vorrei che l'utente fosse in grado di fare clic sul testo del paragrafo e non avere il testo dissolvenza. Se l'utente fa clic sul div esterno (genitore div), tutto svanirà.
superUntitled

@superUntitled - Grazie per il chiarimento ... la risposta è stata aggiornata per fare questo, provalo.
Nick Craver

18
@Asaf: utilizzare e.stopPropagation();invece return false;che per quel caso.
Nick Craver

2
Puoi anche utilizzare }).find('.classes-to-ignore').click(function(e) {per selezionare elementi figlio specifici
Paul Mason,

5
Non capisco perché gli dici di usare e.stopPropagation()e poi usare return falseinvece. return falseè equivalente a e.preventDefault(); e.stopPropagation()quindi potrebbe avere effetti collaterali imprevisti.
Steen Schütt,

183

Sto usando il seguente markup e ho riscontrato lo stesso problema:

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

Qui ho usato la seguente logica:

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

In termini di domanda esatta, posso vedere che funziona come segue:

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

o ovviamente il contrario:

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

Spero che aiuti.


28
Penso che questa sia la soluzione migliore. Non interferisce in alcun modo con i bambini e dovrebbe funzionare meglio in quanto potenzialmente non registra migliaia di callback se ci sono migliaia di bambini.
LucasB,

4
@ l2aelba - dovresti utilizzare .on("click", ...)nelle ultime versioni di jQuery come .live()è stato deprecato dalla v1.7. Vedi api.jquery.com/live
Chris l'

Sì, @Chris ho pubblicato il 16 novembre 12 alle 10:12
l2aelba l'

Spiacenti, probabilmente non è stato necessario fare riferimento al tuo ID. Ho aggiunto il commento in gran parte a chiunque leggesse questa risposta.
Chris,

1
Questa risposta è migliore della risposta accettata in quanto non interrompe alcun evento di clic sugli elementi figlio
cameronjonesweb

24

Oppure puoi anche fare:

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

   // ... //
});

È necessario restituire false, per evitare l'evento click negli elementi figlio. La revisione era sbagliata
dani24,

6

La mia soluzione:

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

Simile alla soluzione sopra la tua.
user460114

3

Personalmente aggiungerei un gestore di clic all'elemento figlio che non ha fatto altro che interrompere la propagazione del clic. Quindi sarebbe simile a:

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

qual è la differenza tra stopPropagatione il ritorno falso come suggeriscono altre risposte?
Crashalot

Credo in questo caso che funzionerebbero allo stesso modo, ma penso che fermare la propagazione sia più chiara allo scopo di ciò che viene fatto e lascia migliori possibilità di capire perché venga fatto in seguito. Ma è discutibile.
Noahone

grazie per il chiarimento. sembra che stopPropagationpotrebbe essere più pulito in quanto non impedirà che si verifichino eventi su elementi figlio, il che può accadere conreturn false .
Crashalot

0

Ecco un esempio Il quadrato verde è il genitore e il quadrato giallo è l'elemento figlio.

Spero che questo aiuti.

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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.