Bagaimana saya mencegah acara onclick orang tua dari menembak ketika jangkar anak diklik?


346

Saat ini saya menggunakan jQuery untuk membuat div yang dapat diklik dan dalam div ini saya juga memiliki jangkar. Masalah yang saya hadapi adalah ketika saya mengklik sebuah anchor, kedua event klik itu menyala (untuk div dan anchor). Bagaimana cara mencegah acara onclick div dari menembak ketika jangkar diklik?

Berikut kode yang rusak:

JavaScript

var url = $("#clickable a").attr("href");

$("#clickable").click(function() {
    window.location = url;
    return true;
})

HTML

<div id="clickable">
    <!-- Other content. -->
    <a href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>

Jawaban:


458

Acara menggelembung ke titik tertinggi di DOM tempat acara klik dilampirkan. Jadi dalam contoh Anda, bahkan jika Anda tidak memiliki elemen lain yang dapat diklik secara eksplisit di div, setiap elemen anak dari div akan menggelembungkan acara klik mereka ke atas DOM hingga penangan event klik DIV menangkapnya.

Ada dua solusi untuk ini adalah memeriksa untuk melihat siapa yang sebenarnya memulai acara tersebut. jQuery melewati objek eventargs bersama acara:

$("#clickable").click(function(e) {
    var senderElement = e.target;
    // Check if sender is the <div> element e.g.
    // if($(e.target).is("div")) {
    window.location = url;
    return true;
});

Anda juga dapat melampirkan pengendali acara klik ke tautan Anda yang memberi tahu mereka untuk berhenti menggelegak setelah penangan mereka menjalankan:

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});

3
Jawaban yang bagus Senang mengetahui ada pilihan juga.
Jonathon Watney

4
+1! Melampirkan pengendali klik dengan stopPropagation adalah trik yang sangat bagus, terima kasih!
Thomas

2
jika Anda memiliki banyak elemen yang ingin Anda hindari propagasi, Anda bisa menemukan elemen induknya dan mencegahnya agar tidak menggelembung di sana juga. Jadi, alih-alih mencegat semua tautan di div, katakanlah misalnya - cukup sadap klik bahkan pada div itu sendiri dan cegah agar tautannya tidak semakin tinggi dan Anda sudah siap.
sucitivel

21
Menggunakan if( e.target !== this) return;di orangtua lebih baik daripada e.stopPropagation()di anak karena Anda tidak pernah tahu jika orang lain melampirkan pawang ke anak-anak, atau jika perpustakaan harus melampirkan pawang ke anak (dan Anda tidak ingin mengacaukan dengan kode perpustakaan). Ini adalah pemisahan keprihatinan yang lebih baik.
UTF_or_Death

3
Menempatkan tanda if( e.target !== this) return;centang di induk berarti bahwa jika salah satu dari anak-anak lain dari orang tua yang tidak memiliki penangan klik sendiri diklik, maka tidak ada yang terjadi. Jadi tidak ada gunanya untuk situasi di mana Anda memiliki misalnya div induk diklik. e.stopPropagation()bekerja dengan baik.
derf26

100

Gunakan metode stopPropagation , lihat contoh:

$("#clickable a").click(function(e) {
   e.stopPropagation();
});

Seperti yang dikatakan oleh jQuery Docs:

stopPropagation Metode mencegah acara melelehkan pohon DOM, mencegah penangan orang tua diberitahu tentang acara tersebut.

Ingatlah bahwa itu tidak benar menghalangi pendengar lain untuk menangani acara ini (mis. Lebih dari satu penangan klik untuk sebuah tombol), jika itu bukan efek yang diinginkan, Anda harus menggunakannya stopImmediatePropagation.


48

Di sini solusi saya untuk semua orang di luar sana mencari kode non-jQuery (javascript murni)

document.getElementById("clickable").addEventListener("click", function( e ){
    e = window.event || e; 
    if(this === e.target) {
        // put your code here
    }
});

Kode Anda tidak akan dieksekusi jika diklik pada anak-anak orang tua


1
Ini bekerja untuk saya, saya membutuhkan solusi non-JS / jQuery. 10x!
LA

Jawaban yang bagus Saya baru saja melewati acara tersebut secara langsung. Jadi saya tidak menggunakan window.event, yang MDN tidak menyarankan: developer.mozilla.org/en-US/docs/Web/API/Window/event . Jika Anda dapat meluangkan waktu, saya akan sangat menghargai jika Anda dapat berkomentar mengapa Anda menggunakan window.event(mungkin itu adalah masalah yang ada pada tahun 2015 atau saya gagal memahami alasannya).
RM

15

Anda juga dapat mencoba ini

$("#clickable").click(function(event) {
   var senderElementName = event.target.tagName.toLowerCase();
   if(senderElementName === 'div')
   {
       // do something here 
   } 
   else
   {
      //do something with <a> tag
   }
});

14

Jika Anda tidak berniat untuk berinteraksi dengan elemen dalam / dalam hal apa pun, maka solusi CSS mungkin berguna untuk Anda.

Cukup atur elemen dalam ke pointer-events: none

dalam kasus Anda:

.clickable > a {
    pointer-events: none;
}

atau untuk menargetkan semua elemen dalam secara umum:

.clickable * {
    pointer-events: none;
}

Peretasan mudah ini menyelamatkan saya banyak waktu saat berkembang dengan ReactJS

Dukungan peramban dapat ditemukan di sini: http://caniuse.com/#feat=pointer-events


8

Jika Anda memiliki banyak elemen di div yang dapat diklik, Anda harus melakukan ini:

$('#clickable *').click(function(e){ e.stopPropagation(); });

8

Menggunakan return false;atau e.stopPropogation();tidak akan membiarkan kode lebih lanjut dieksekusi. Ini akan berhenti mengalir pada titik ini sendiri.


Ya, ini penting - lari ke ini sendiri. Tetapi jawaban di atas dari Rex sangat membantu - bisa mendapatkan elemen yang diklik, dan dalam beberapa kasus menggunakan ini dalam logika yang Anda coba hentikan. .target.nodeName juga membantu mendapatkan gagasan yang jelas tentang apa yang dipukul.
Watercayman


4

Alternatif Sebaris:

<div>
    <!-- Other content. -->
    <a onclick='event.stopPropagation();' href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>

3

Berikut ini contoh menggunakan Angular 2+

Misalnya, jika Anda ingin menutup Komponen Modal jika pengguna mengklik di luarnya:

// Close the modal if the document is clicked.

@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
  this.closeModal();
}

// Don't close the modal if the modal itself is clicked.

@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
  event.stopPropagation();
}

1

Anda harus menghentikan acara dari mencapai (menggelegak ke) orang tua (div). Lihat bagian tentang menggelegak di sini , dan info API khusus jQuery di sini .


Keren. Terima kasih atas info tentang acara yang menggelegak.
Jonathon Watney

1

var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);

function innerFunction(event){
  event.stopPropagation();
  console.log("Inner Functiuon");
}

function outerFunction(event){
  console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
  <div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>


0

Untuk menentukan beberapa sub elemen sebagai tidak dapat ditulis, tulis hierarki css seperti pada contoh di bawah ini.

Dalam contoh ini saya menghentikan propagasi ke elemen (*) di dalam td di dalam tr di dalam tabel dengan kelas ".subtable"

$(document).ready(function()
{    
   $(".subtable tr td *").click(function (event)
   {
       event.stopPropagation();
   });

});

0

AbaikanParent () adalah solusi JavaScript murni.

Ini berfungsi sebagai lapisan perantara yang membandingkan koordinat klik mouse dengan koordinat elemen anak. Dua langkah implementasi sederhana:

1. Masukkan kode ignParent () pada halaman Anda.

2. Alih-alih onclick asli orang tua = "parentEvent ();" , menulis:

onclick="ignoreParent(['parentEvent()', 'child-ID']);"

Anda dapat mengirimkan ID dari sejumlah elemen anak ke fungsi, dan mengecualikan yang lain.

Jika Anda mengklik salah satu elemen anak, acara induk tidak menyala. Jika Anda mengklik orangtua, tetapi tidak pada salah satu elemen anak [disediakan sebagai argumen], acara induk dipecat.

kode ignParent () pada Github


0

Jika berada dalam konteks sebaris, dalam HTML coba ini:

onclick="functionCall();event.stopPropagation();

-1

Jika seseorang memiliki masalah ini menggunakan Bereaksi, ini adalah bagaimana saya menyelesaikannya.

scss:

#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }

#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }

Pembuatan komponen ():

render() {
    ...
    return (
        <div id='loginBackdrop' onClick={this.props.closeLogin}>
            <div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
             ... [modal content] ...
            </div>
        </div>
    )
}

Dengan menambahkan fungsi onClick untuk aktivitas klik mouse modal anak (konten div) dicegah untuk mencapai fungsi 'closeLogin' dari elemen induk.

Ini melakukan trik untuk saya dan saya dapat membuat efek modal dengan 2 div sederhana.


-3

tambahkan asebagai berikut:

<a href="http://foo.com" onclick="return false;">....</a>

atau return false;dari click handler untuk #clickablelike:

  $("#clickable").click(function() {
        var url = $("#clickable a").attr("href");
        window.location = url;
        return false;
   });

-3

Semua solusi itu rumit dan jscript. Ini adalah versi paling sederhana:

var IsChildWindow=false;

function ParentClick()
{
    if(IsChildWindow==true)
    {
        IsChildWindow==false;
        return;
    }
    //do ur work here   
}


function ChildClick()
{
    IsChildWindow=true;
    //Do ur work here    
}

3
saya pikir Anda membuat kesalahan di baris "IsChildWindow == false;" - bukankah seharusnya "IsChildWindow = false;"?
Andre Schweighofer

-5
<a onclick="return false;" href="http://foo.com">I want to ignore my parent's onclick event.</a>

5
Ini juga mencegah tautan dari navigasi.
Rex M

Ya atau tidak apa yang dibutuhkan? Atau perlu nevegar?
andres descalzo
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.