JQuery остановить дочерний запуск родительского события

208

У меня есть div, к которому я прикрепил onclickсобытие. в этом разделе есть тег со ссылкой. Когда я нажимаю на ссылку, onclickсобытие из div также запускается. Как я могу отключить это, чтобы, если ссылка нажата на div onclickне срабатывает?

сценарий:

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

HTML-код:

<div class="header">
    <a href="link.html">some link</a>
    <ul class="children">
        <li>some list</li>
    </ul>
</div>
Джон
источник

Ответы:

412

Сделай это:

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

Если вы хотите узнать больше о .stopPropagation (), посмотрите здесь .

Ник Крейвер
источник
2
если это поможет кому - то, я заменил $(".header a")с $(".header *")и получил какой - либо ребенок выбран (Div, формы, ввод и т.д.).
aldo.roman.nurena
1
e.stopPropagation (); должен быть написан в первой строке, если это не работает!
Ehsan
2
к сожалению, этот метод не позволяет relсконфигурированному лайтбоксу функционировать
eapo
5
Ответ ниже xr280xr намного лучше, так как он не мешает возможным событиям детей.
Александр Янк,
1
Вы создаете больше проблем, чем решаете. Представьте сторонние плагины, прослушивающие событие нажатия на элементе документа. Они никогда не узнают об этих кликах. Смотрите комментарий о лайтбоксе.
Салман А
100

Или вместо того, чтобы иметь дополнительный обработчик событий для предотвращения другого обработчика, вы можете использовать аргумент Event Object, передаваемый вашему обработчику события click, чтобы определить, был ли выбран дочерний элемент. targetбудет currentTargetвыбранным элементом и будет .header div:

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

     $(this).children(".children").toggle();
});
xr280xr
источник
8
Для меня это более элегантное решение, так как вам не нужно добавлять явный warnDefault () к каждому дочернему элементу.
Райан Григгс
5
И это работает, если у вас есть независимые события на ребенка в отличие от принятого ответа. Определенно более чистое и лучшее решение
BozanicJosip
2
В большинстве случаев вы не будете заботиться об этом, но если по какой-либо причине вам необходимо поддерживать IE6-8, они не имеютcurrentTarget . Обходной путь должен заменить это this, как предложено в другом ответе .
Александр Янк
Это более чистое решение, чем установка дополнительного слушателя, чтобы просто ловить клики.
Micros
этот код работал лучше для меня `var target = $ (e.target); if (! target.is ("span")) return; `
Cr1xus
17

Лучше всего использовать on () с цепочкой вроде,

$(document).ready(function(){
    $(".header").on('click',function(){
        $(this).children(".children").toggle();
    }).on('click','a',function(e) {
        e.stopPropagation();
   });
});
Рохан Кумар
источник
4

Ответы здесь восприняли вопрос ОП слишком буквально. Как эти ответы можно расширить в сценарий, где есть МНОГИЕ дочерние элементы, а не просто один<a> тег? Вот один из способов.

Допустим, у вас есть фотогалерея с затемненным фоном и фотографиями по центру в браузере. Когда вы щелкаете черный фон (но не что-то внутри него), вы хотите, чтобы наложение закрылось.

Вот несколько возможных 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>

И вот как JavaScript будет работать:

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

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

Это остановит события щелчка по элементам внутри .contentsкаждого исследования, .galleryпоэтому галерея будет закрываться только тогда, когда вы щелкнете по заштрихованной области черного фона, но не при щелчке в области содержимого. Это может быть применено ко многим различным сценариям.

Gavin
источник
4

Я наткнулся на этот вопрос, ища другой ответ.

Я хотел, чтобы все дети не вызывали родителя.

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

Или это:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        return false;
   });
});
user719004
источник
2
@ Halcyon991 e передается в любом случае через аргументы, e просто ссылка
qodeninja
@qodeninja Да, но ненужное добавление символов, если оно не используется.
Halcyon991
Нет смысла добавлять return falseссылку, она должна быть кликабельной.
2016 г.
0

Самое простое решение - добавить этот CSS для детей:

.your-child {
    pointer-events: none;
}
пирс
источник
Мне нужно было это для тега нежелательных шрифтов, добавленного Wordpress, и это сработало для меня
Ndm Gjr
-1

Более короткий способ сделать это:

$('.header').on('click', function () {
    $(this).children('a').on('click', function(e) {
        e.stopPropagation();
        $(this).siblings('.children').toggle();
    });
});
Андреас 'Энди' Берггрин
источник
Но ... Это ничего не делает при нажатии на заголовок.
Лиора Хайдонт,
Каждый раз, когда вы щелкаете по заголовку, это добавляет новое событие щелчка к дочерним элементам ('a').
Фрэнк Форте