jQuery: fungsi klik mengecualikan anak-anak.


144

Mencoba membungkus kepala saya di sekitar fungsi jQuery ".not ()", dan mengalami masalah. Saya ingin agar div induk menjadi "dapat diklik" tetapi jika pengguna mengklik elemen anak, skrip tidak dipanggil.

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

html:

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

Jawaban:


198

Untuk melakukan ini, hentikan klik pada anak menggunakan .stopPropagation :

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

Ini akan menghentikan klik anak menggelembung melewati level mereka sehingga orang tua tidak akan menerima klik.

.not() digunakan sedikit berbeda, itu menyaring elemen dari pemilih Anda, misalnya:

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

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

Untuk mengklik, masalah Anda adalah bahwa klik pada anak muncul hingga induknya , bukan karena Anda secara tidak sengaja telah melampirkan handler klik pada anak.


terima kasih nick, saya tidak berpikir bahwa ini adalah apa yang saya cari. Saya minta maaf karena pertanyaan saya tidak jelas. Saya ingin seluruh div.example untuk fadeOut, hanya ketika elemen induk diklik, bukan ketika div anak diklik. Alasan untuk ini adalah saya ingin pengguna dapat mengklik teks paragraf dan tidak memiliki teks fadeOut. Jika pengguna mengklik div luar (induk div), maka semuanya akan pudar.
superUtitle

@superUntitle - Terima kasih atas klarifikasi ... jawabannya diperbarui untuk melakukan ini, cobalah.
Nick Craver

18
@ Asaf - gunakan e.stopPropagation();sebagai ganti return false;untuk kasus itu.
Nick Craver

2
Anda juga dapat menggunakan }).find('.classes-to-ignore').click(function(e) {untuk memilih elemen anak tertentu
Paul Mason

5
Saya tidak mengerti mengapa Anda memintanya untuk menggunakan e.stopPropagation()dan kemudian menggunakannya return false. return falsesetara dengan e.preventDefault(); e.stopPropagation()sehingga mungkin memiliki efek samping yang tidak diharapkan.
Steen Schütt

183

Saya menggunakan markup berikut dan mengalami masalah yang sama:

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

Di sini saya telah menggunakan logika berikut:

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

Dalam hal pertanyaan yang tepat, saya dapat melihat bahwa berfungsi sebagai berikut:

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

atau tentu saja sebaliknya:

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

Semoga itu bisa membantu.


28
Saya pikir ini adalah solusi yang lebih baik. Itu tidak mengganggu anak-anak dengan cara apa pun dan itu harus berkinerja lebih baik karena tidak berpotensi mendaftarkan ribuan panggilan balik jika ada ribuan anak-anak.
LucasB

4
@ l2aelba - Anda harus menggunakan .on("click", ...)dalam versi terbaru jQuery seperti yang .live()telah ditinggalkan sejak v1.7. Lihat api.jquery.com/live
Chris

Ya, @ Chris, saya memposting pada 16 November '12 pada 10:12
l2aelba

Maaf, mungkin tidak perlu referensi ID Anda. Saya menambahkan komentar sebagian besar untuk orang lain yang membaca jawaban ini.
Chris

1
Jawaban ini lebih baik daripada jawaban yang diterima karena tidak mengganggu acara klik pada elemen anak
cameronjonesweb

24

Atau Anda juga bisa:

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

   // ... //
});

Anda harus mengembalikan false, untuk menghindari peristiwa klik di elemen anak-anak. Revisi itu salah
dani24

6

Solusi saya:

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

Mirip dengan solusi di atas milik Anda.
user460114

3

Saya pribadi akan menambahkan handler klik ke elemen anak yang tidak melakukan apa pun selain menghentikan penyebaran klik tersebut. Jadi akan terlihat seperti:

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

apa perbedaan antara stopPropagationdan mengembalikan false seperti yang disarankan jawaban lain?
Crashalot

Saya percaya dalam kasus ini mereka akan berfungsi sama, tetapi saya pikir berhenti propagasi lebih jelas dengan tujuan apa yang dilakukan dan meninggalkan peluang yang lebih baik untuk memahami mengapa hal itu dilakukan nanti. Tapi ini masih bisa diperdebatkan.
Noahone

terimakasih atas klarifikasinya. sepertinya stopPropagationmungkin lebih bersih karena tidak akan menghentikan peristiwa pada elemen anak terjadi, yang mungkin terjadi dengan return false.
Crashalot

0

Berikut ini sebuah contoh. Kotak hijau adalah induk dan kotak kuning adalah elemen anak.

Semoga ini bisa membantu.

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>

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.