jquery stop potomek wyzwala zdarzenie nadrzędne


208

Mam div, do którego przypisałem onclickwydarzenie. w tym div znajduje się tag z linkiem. Kiedy kliknę link, onclickwywołane zostanie również zdarzenie z div. Jak mogę to wyłączyć, aby kliknięcie linku na div onclicknie było uruchamiane?

scenariusz:

$(document).ready(function(){
    $(".header").bind("click", function(){
         $(this).children(".children").toggle();
    });
})

Kod HTML:

<div class="header">
    <a href="link.html">some link</a>
    <ul class="children">
        <li>some list</li>
    </ul>
</div>

Odpowiedzi:


411

Zrób to:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        e.stopPropagation();
   });
});

Jeśli chcesz przeczytać więcej na temat .stopPropagation (), spójrz tutaj .


2
czy to pomaga kogoś, wymieniłem $(".header a")z $(".header *")i dostał Każde dziecko wybiera (div, formularze, wejście, etc).
aldo.roman.nurena

1
e.stopPropagation (); musi być napisane w pierwszej linii, chyba że to nie działa!
ehsan

2
niestety ta metoda uniemożliwia działanie relskonfigurowanego
lightboksa

5
Poniższa odpowiedź autorstwa xr280xr jest znacznie lepsza, ponieważ nie koliduje z możliwymi zdarzeniami dzieci.
Alexander Jank

1
Tworzysz więcej problemów niż rozwiązujesz. Wyobraź sobie, że wtyczki innych firm nasłuchują zdarzenia kliknięcia na elemencie dokumentu. Nigdy nie dowiedzą się o tych kliknięciach. Zobacz komentarz na temat lightbox.
Salman A

100

Lub zamiast posiadania dodatkowej procedury obsługi zdarzeń w celu zapobieżenia innej procedurze obsługi, możesz użyć argumentu Obiekt zdarzenia przekazanego do procedury obsługi zdarzenia kliknięcia, aby ustalić, czy dziecko zostało kliknięte. targetbędzie klikniętym elementem i currentTargetbędzie div .header:

$(".header").click(function(e){
     //Do nothing if .header was not directly clicked
     if(e.target !== e.currentTarget) return;

     $(this).children(".children").toggle();
});

8
Dla mnie jest to bardziej eleganckie rozwiązanie, ponieważ nie musisz dodawać jawnego zapobieganiaDefault () do każdego elementu potomnego.
Ryan Griggs

5
I działa, jeśli masz niezależne wydarzenia na dziecku w przeciwieństwie do zaakceptowanej odpowiedzi. Zdecydowanie czystsze i lepsze rozwiązanie
BozanicJosip

2
W większości przypadków nie będziesz się tym przejmować, ale jeśli z jakiegoś powodu potrzebujesz obsługi IE6-8, nie mającurrentTarget . Obejściem tego problemu jest zastąpienie go this, jak sugerowano w innej odpowiedzi .
Alexander Jank

Jest to czystsze rozwiązanie niż ustawianie dodatkowego odbiornika, aby po prostu łapał kliknięcia.
Micros

ten kod działał dla mnie lepiej var var = $ (e.target); if (! target.is ("span")) return; `
Cr1xus

17

Lepszy sposób, używając on () z łańcuchami typu,

$(document).ready(function(){
    $(".header").on('click',function(){
        $(this).children(".children").toggle();
    }).on('click','a',function(e) {
        e.stopPropagation();
   });
});

4

Odpowiedzi tutaj przyjęły pytanie OP zbyt dosłownie. Jak te odpowiedzi można rozwinąć w scenariusz, w którym WIELE elementów potomnych, a nie tylko jednego <a>znacznika? Oto jeden sposób.

Załóżmy, że masz galerię zdjęć z zaciemnionym tłem i zdjęciami wyśrodkowanymi w przeglądarce. Po kliknięciu czarnego tła (ale niczego w nim) nie chcesz, aby nakładka została zamknięta.

Oto kilka możliwych HTML:

<div class="gallery" style="background: black">
    <div class="contents"> <!-- Let's say this div is 50% wide and centered -->
        <h1>Awesome Photos</h1>
        <img src="img1.jpg"><br>
        <img src="img2.jpg"><br>
        <img src="img3.jpg"><br>
        <img src="img4.jpg"><br>
        <img src="img5.jpg">
    </div>
</div>

A oto jak działa JavaScript:

$('.gallery').click(
    function()
    {
        $(this).hide();
    }
);

$('.gallery > .contents').click(
    function(e) {
        e.stopPropagation();
    }
);

To zatrzyma zdarzenia kliknięcia z elementów wewnątrz .contentskażdego badania, .gallerywięc galeria zostanie zamknięta tylko po kliknięciu wyblakłego czarnego obszaru tła, ale nie po kliknięciu w obszarze zawartości. Można to zastosować do wielu różnych scenariuszy.


4

Natknąłem się na to pytanie, szukając innej odpowiedzi.

Chciałem uniemożliwić wszystkim dzieciom wyzwolenie rodzica.

JavaScript:

document.getElementById("parent").addEventListener("click",  function (e) {
    if (this !== event.target) return;
    // Do something
});

jQuery:

$("#parent").click(function () {
    // Do something
}).children().on("click", function (e) {
    e.stopPropagation();
});

0

Albo to:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        return false;
   });
});

2
@ Halcyon991 e jest przekazywany w jakikolwiek sposób przez argumenty, e to tylko odniesienie
qodeninja

@qodeninja Tak, ale niepotrzebny dodatek postaci, jeśli nie jest używany.
Halcyon991

Nie ma sensu dodawać return falselinku, powinien być klikalny.
eapo

0

Najprostszym rozwiązaniem jest dodanie tego CSS do dzieci:

.your-child {
    pointer-events: none;
}

Potrzebowałem tego do niechcianego tagu czcionki dodanego przez Wordpress i zadziałało to dla mnie
Ndm Gjr

-1

Krótszy sposób, aby to zrobić:

$('.header').on('click', function () {
    $(this).children('a').on('click', function(e) {
        e.stopPropagation();
        $(this).siblings('.children').toggle();
    });
});

Ale ... To nic nie robi po kliknięciu nagłówka.
Liora Haydont,

Każde kliknięcie nagłówka powoduje dodanie nowego zdarzenia kliknięcia do dzieci („a”).
Frank Forte
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.