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.

CaptSaltyJack
sumber

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>

user1106925
sumber
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

hobberwickey
sumber
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();
});
ori
sumber
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
@cgogolin, lihat ini: stackoverflow.com/questions/12197122/…
Jessica
28

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

if(e.target !== e.currentTarget) return;
Jens Törnell
sumber
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/

Jasper
sumber
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
})
Michalis
sumber
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)

Wonx2150
sumber
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'
});
Wukadin
sumber
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>

Dejan Markovic
sumber
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

Xenxier
sumber
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>

Omar bakhsh
sumber