Bir alt çapa tıklandığında bir ebeveynin onclick etkinliğinin tetiklenmesini nasıl önleyebilirim?


348

Şu anda bir div tıklanabilir yapmak için jQuery kullanıyorum ve bu div de çapa var. Bir çapa tıkladığımda, her iki tıklama olayının da tetiklediği (div ve çapa için). Bir çapa tıklandığında div'ın onclick etkinliğinin tetiklenmesini nasıl önleyebilirim?

İşte bozuk kod:

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>

Yanıtlar:


460

Etkinlikler, DOM'da bir tıklama etkinliğinin eklendiği en yüksek noktaya taşınır. Örneğinizde, div'de açıkça tıklanabilir başka öğeleriniz olmasa bile, div'in her alt öğesi, DIV'nin click event handler'i yakalayana kadar tıklama olaylarını DOM'ya kadar gönderir.

Bunun iki çözümü vardır, olayın gerçekte kimin kaynaklandığını kontrol etmektir. jQuery olayla birlikte bir eventargs nesnesi iletir:

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

Ayrıca, bağlantılarınıza kendi işleyicileri yürütüldükten sonra olay köpürmesini durdurmalarını söyleyen bir tıklama olay işleyicisi de ekleyebilirsiniz :

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

3
Mükemmel cevap. Seçenekler de olduğunu bilmek güzel.
Jonathon Watney

4
1! StopPropagation ile bir tıklama işleyicisi eklemek çok güzel bir numara, teşekkürler!
Thomas

2
Eğer yayılmayı önlemek istediğiniz bir grup elementiniz varsa, ana elementlerini bulabilir ve kafa da orada kabarcıklanmalarını önleyebilir. Yani bir div'deki tüm bağlantıları kesmek yerine, örneğin diyelim ki - div'in kendisinde bile tıklamayı durdurun ve daha yükseğe çıkmasını engelleyin ve hazırsınız.
sucitivel

21
Ebeveynte kullanmak çocuktan if( e.target !== this) return;daha iyidir e.stopPropagation()çünkü birisinin çocuklara başka bir işleyici ekleyip eklemediğini veya bir kütüphanenin bir çocuğa bir işleyici iliştirmesi gerekip gerekmediğini (ve kütüphane koduyla uğraşmak istemediğinizi) asla bilemezsiniz. Endişelerin daha iyi ayrılması.
UTF_or_Death

3
if( e.target !== this) return;Çekin üst öğeye yerleştirilmesi , söz konusu üst öğenin onClick işleyicileri olmayan diğer alt öğelerinden herhangi birinin tıklanması durumunda hiçbir şeyin gerçekleşmeyeceği anlamına gelir. Dolayısıyla, tıklanabilir bir üst div bölümünün olduğu bir durum için işe yaramaz. e.stopPropagation()ancak iyi çalışıyor.
derf26

101

StopPropagation yöntemini kullanın , bir örneğe bakın:

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

JQuery Docs tarafından söylendiği gibi:

stopPropagation yöntemi, etkinliğin DOM ağacını köpürmesini önleyerek üst işleyicilerin olayla ilgili bildirim almasını engeller.

Diğer dinleyicilerin bu olayı işlemesini engellemediğini unutmayın (örn. Bir düğme için birden fazla tıklama işleyicisi), istenen efekt değilse, stopImmediatePropagationbunun yerine kullanmanız gerekir .


48

Burada benim olmayan bir jQuery kodu (saf javascript) arayan herkes için benim çözüm

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

Ebeveynin çocuklarına tıklanırsa kodunuz yürütülmez


1
Bu benim için çalıştı, JS / jQuery olmayan bir çözüme ihtiyacım vardı. 10x!
LA

Mükemmel cevap. Etkinliği doğrudan geçtim. Bu yüzden kullanmadım window.event, hangi MDN cesaretini kırıyor: developer.mozilla.org/en-US/docs/Web/API/Window/event . Eğer zaman ayırabiliyorsanız, neden kullandığınızı yorumlayabiliyorsanız çok memnun olurum window.event(belki de 2015'te var olan bir sorundur veya sebebini anlayamadım).
RMo

15

bunu da deneyebilirsin

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

14

Her durumda iç eleman (lar) ile etkileşime girmeyi düşünmüyorsanız, bir CSS çözümü sizin için yararlı olabilir.

Sadece iç eleman (lar) ı pointer-events: none

Senin durumunda:

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

veya genel olarak tüm iç unsurları hedeflemek için:

.clickable * {
    pointer-events: none;
}

Bu kolay saldırı, ReactJS ile geliştirirken bana çok zaman kazandırdı

Tarayıcı desteği şu adreste bulunabilir: http://caniuse.com/#feat=pointer-events


8

Tıklanabilir div'da birden çok öğeniz varsa, bunu yapmanız gerekir:

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

8

Kullanılması return false;veya e.stopPropogation();daha fazla kod yürütmesine izin vermez. Bu noktada akışı durduracaktır.


Evet, bu önemli - bunu kendim gördüm. Ancak Rex'in yukarıdaki cevabı yararlıdır - tıklanan öğeyi alabilir ve bazı durumlarda bunu durdurmaya çalıştığınız mantıkta kullanabilirsiniz. .target.nodeName, neyin vurulduğuna dair net bir fikir edinmek için de yardımcı oldu.
Watercayman

8

Herhangi birinin ihtiyacı varsa yazma (benim için çalıştı):

event.stopImmediatePropagation()

Gönderen bu çözümü.


4

Satır İçi Alternatif:

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

3

İşte Angular 2+ kullanan bir örnek

Örneğin, kullanıcı bileşeninin dışını tıklarsa bir Kalıcı Bileşeni kapatmak istiyorsanız:

// 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

Etkinliğin ebeveyne (div) ulaşmasını (köpürmesini) durdurmanız gerekir. Burada köpürme ile ilgili kısma ve jQuery'ye özel API bilgilerine buradan bakın .


Güzel. Olay köpürme hakkında bilgi için teşekkürler.
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

Bazı alt öğeleri seçilemez olarak belirtmek için aşağıdaki örnekte olduğu gibi css hiyerarşisini yazın.

Bu örnekte, ".subtable" sınıfına sahip bir tablonun içindeki td içindeki tr içindeki herhangi bir öğeye (*) yayılmasını durduruyorum.

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

});

0

ignoreParent () saf bir JavaScript çözümüdür.

Fare tıklatmasının koordinatlarını, alt öğelerin / öğelerin koordinatlarıyla karşılaştıran bir ara katman olarak çalışır. İki basit uygulama adımı:

1. ignoreParent () kodunu sayfanıza yerleştirin.

2. Üst öğenin orijinal yerine yerine onclick = "parentEvent ();" , yazmak:

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

Herhangi bir sayıda alt öğenin kimliklerini işleve iletebilir ve diğerlerini hariç tutabilirsiniz.

Alt öğelerden birini tıkladıysanız, üst etkinlik tetiklenmez. Üst öğeyi tıkladıysanız, ancak [bağımsız değişken olarak sağlanan] alt öğelerin hiçbirini seçmediyseniz, üst etkinlik tetiklenir.

Github'daki ignoreParent () kodu


0

Satır içi bağlamdaysa, HTML'de şunu deneyin:

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

-1

Birisi React kullanarak bu sorunu yaşarsa, bu şekilde çözdüm.

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; }

Bileşenin render ():

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

Alt mod (içerik div) fare tıklatma olayları için bir onClick işlevi ekleyerek, üst öğenin 'closeLogin' işlevine ulaşması engellenir.

Bu benim için hile yaptı ve 2 basit div ile kalıcı bir etki yaratabildim.


-3

aaşağıdaki gibi ekleyin :

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

veya aşağıdakiler return false;için tıklama işleyicisinden #clickable:

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

-3

Tüm çözüm karmaşık ve jscripttir. İşte en basit sürüm:

var IsChildWindow=false;

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


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

3
Sanırım doğrultusunda bir hata yaptım "IsChildWindow == false;" - "IsChildWindow = false;" olmamalı mı?
Andre Schweighofer

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

5
Bu, bağlantının gezinmesini de engeller.
Rex M

Evet, ya da ne gerekli değil mi? Ya da nevegar olmanız mı gerekiyor?
andres descalzo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.