Bagaimana acara klik HANYA menembaki DIV orang tua, bukan anak-anak?


211

Saya memiliki DIV dengan kelas foobar, dan beberapa DIV di dalam DIV yang tidak kelas, tapi saya kira mereka mewarisi foobarkelas:

$('.foobar').on('click', function() { /*...do stuff...*/ });

Saya ingin itu untuk mematikan hanya ketika mengklik suatu tempat di DIV tetapi tidak pada anak-anaknya DIV.

Jawaban:


439

Jika e.targetelemennya sama dengan this, Anda belum mengklik turunan.

$('.foobar').on('click', function(e) {
  if (e.target !== this)
    return;
  
  alert( 'clicked the foobar' );
});
.foobar {
  padding: 20px; background: yellow;
}
span {
  background: blue; color: white; padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='foobar'> .foobar (alert) 
  <span>child (no alert)</span>
</div>


Jawaban itu menjelaskan komentar ini
gdoron mendukung Monica

@ gdoron: Adam bersikap terlalu baik. :)

1
Hai @vicky. Hanya FYI, JavaScript memiliki dua jenis perbandingan kesetaraan nilai yang berbeda. The ===atau !==penggunaan yang "ketat Kesetaraan Perbandingan Algoritma" , sedangkan ==dan !=penggunaan yang "Abstrak Kesetaraan Perbandingan Algoritma" , yang merupakan jenis koersif. Kebijaksanaan umum adalah untuk selalu menggunakan perbandingan ketat kecuali ada kebutuhan khusus untuk tipe paksaan (karena aturannya sedikit rumit) . Dalam hal ini, karena objek dibandingkan, itu benar-benar tidak membuat perbedaan, tetapi Anda akan menemukan bahwa kebanyakan orang masih akan tetap dengan perbandingan yang ketat .

1
@vicky: Tidak apa-apa. Itu masih benar. Membiarkan Anda saja JS memiliki operator yang berbeda. ;-)

3
Ini adalah jawaban yang bagus karena ini juga dapat bekerja dengan addEventListener Vanilla JS dan tidak spesifik jQuery.
Michael Giovanni Pumo

64

Ada cara lain yang berfungsi jika Anda tidak keberatan hanya menargetkan peramban yang lebih baru. Cukup tambahkan CSS

pointer-events: none;

untuk setiap anak dari div yang ingin Anda ambil klik. Inilah tabel dukungan

http://caniuse.com/#feat=pointer-events


13
Ketahuilah bahwa saya harus menghindari menulis komentar 'terima kasih', tetapi saya dapat mencium kaki Anda untuk ini :-)
Simona Adriani

@SimonaAdriani ya?
n3wb

Terima kasih, saya melakukan hal yang sama, tetapi saya berjuang untuk menulis unit test case di sekitarnya. Bagaimana saya bisa memastikan clickpemicu acara klik programatik harus diblokir?
Pankaj Parkar

29

Anda dapat menggunakan bubbling sesuai keinginan Anda:

$('.foobar').on('click', function(e) {
    // do your thing.
}).on('click', 'div', function(e) {
    // clicked on descendant div
    e.stopPropagation();
});

Ini terlihat seperti solusi yang bagus untuk skenario spesifik saya, karena saya hanya ingin mengecualikan klik pada <a>elemen turunan . Hanya ada satu masalah: Ketika saya klik tengah pada mereka, acara masih memicu (diuji di Google Chrome). Apakah ada varian dari ini yang juga mencegah ini?
cgogolin


28

Saya tidak mendapatkan jawaban yang diterima untuk bekerja, tetapi ini tampaknya berhasil, setidaknya di vanilla JS.

if(e.target !== e.currentTarget) return;

1
e.currentTarget lebih akurat daripada referensi thiskarena objek yang thismenunjuk dapat berubah tergantung pada ruang lingkup dan konteks dari mana ia disebut
eballeste

20
//bind `click` event handler to the `.foobar` element(s) to do work,
//then find the children of all the `.foobar` element(s)
//and bind a `click` event handler to them that stops the propagation of the event
$('.foobar').on('click', function () { ... }).children().on('click', function (event) {
    event.stopPropagation();
    //you can also use `return false;` which is the same as `event.preventDefault()` and `event.stopPropagation()` all in one (in a jQuery event handler)
});

Ini akan menghentikan penyebaran (penggelembungan) clickacara pada salah satu elemen anak-anak dari .foobarelemen sehingga acara tidak akan mencapai.foobar elemen untuk memecat event handler mereka.

Berikut ini adalah demo: http://jsfiddle.net/bQQJP/


3
$(".advanced ul li").live('click',function(e){
    if(e.target != this) return;
    //code
    // this code will execute only when you click to li and not to a child
})

2

Saya memiliki masalah yang sama dan muncul dengan solusi ini (berdasarkan jawaban lain)

 $( ".newsletter_background" ).click(function(e) {
    if (e.target == this) {
        $(".newsletter_background").hide();
    } 
});

Pada dasarnya dikatakan jika targetnya adalah div kemudian jalankan kodenya jika tidak lakukan apa-apa (jangan sembunyikan)


1

Kasus saya serupa tetapi ini adalah kesempatan ketika Anda memiliki sedikit foobar -s, dan Anda ingin menutup hanya satu - per satu klik:

Temukan kasing induk

$(".foobar-close-button-class").on("click", function () {
    $(this).parents('.foobar').fadeOut( 100 );
    // 'this' - means that you finding some parent class from '.foobar-close-button-class'
    // '.parents' -means that you finding parent class with name '.foobar'
});

Temukan kasing anak

$(".foobar-close-button-class").on("click", function () {
    $(this).child('.foobar-close-button-child-class').fadeOut( 100 );
    // 'this' - means that you finding some child class from '.foobar-close-button-class'
    // '.child' -means that you finding child class with name '.foobar-close-button-child-class'
});

1

Anda dapat menggunakan event.currentTarget. Ini akan melakukan event klik hanya elemnt yang mendapat acara.

target = e => {
    console.log(e.currentTarget);
  };
<ul onClick={target} className="folder">
      <li>
        <p>
          <i className="fas fa-folder" />
        </p>
      </li>
    </ul>


1

Jika Anda tidak dapat menggunakan pointer-events: none;dan menargetkan browser modern yang dapat Anda gunakan composedPathuntuk mendeteksi klik langsung pada objek seperti:

element.addEventListener("click", function (ev) {
    if (ev.composedPath()[0] === this) {
        // your code here ...
    }
})

Anda dapat membaca lebih lanjut tentang compompath di sini: https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath


0

// if its li get value 
document.getElementById('li').addEventListener("click", function(e) {
                if (e.target == this) {
                    UodateNote(e.target.id);
                }
                })
                
                
                function UodateNote(e) {

    let nt_id = document.createElement("div");
    // append container to duc.
    document.body.appendChild(nt_id);
    nt_id.id = "hi";
    // get conatiner value . 
    nt_id.innerHTML = e;
    // body...
    console.log(e);

}
li{
 cursor: pointer;
    font-weight: bold;
  font-size: 20px;
    position: relative;
    width: 380px;
    height: 80px;
    background-color: silver;
    justify-content: center;
    align-items: center;
    text-align: center;
    margin-top: 0.5cm;
    border: 2px solid purple;
    border-radius: 12%;}
    
    p{
     cursor: text;
  font-size: 16px;
   font-weight: normal;
    display: block;
    max-width: 370px;
    max-height: 40px;
    overflow-x: hidden;}
<li id="li"><p>hi</p></li>

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.