jquery зупиняє батьківську подію, що запускає дитину


208

У мене є дів, до якого я долучив 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>

Відповіді:


411

Зробити це:

$(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
Ви створюєте більше проблем, ніж вирішуєте. Уявіть, що плагіни третьої сторони слухають події клацання на елементі документа. Вони ніколи не дізнаються про ці клацання. Дивіться коментар про lightbox.
Салман А

100

Або замість того, щоб мати додатковий обробник подій, щоб запобігти іншому оброблювачу, ви можете використовувати аргумент " Об'єкт події", переданий вашому оброблювачу подій клацання, щоб визначити, чи натиснули дитину. targetбуде елементом, що клацнув, і currentTargetбуде ділом .header:

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

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

8
Для мене це більш елегантне рішення, оскільки вам не потрібно додавати явний prevenDefault () до кожного дочірнього елемента.
Райан Гріггс

5
І це працює, якщо у вас є незалежні події на дитину на відміну від прийнятої відповіді. Безумовно, чистіше і краще рішення
BozanicJosip

2
За більшості обставин ви цього не будете дбати, але якщо з будь-якої причини вам потрібно підтримати IE6-8, у них цього немаєcurrentTarget . Вирішення проблеми полягає в заміні цього this, як це запропоновано в іншій відповіді .
Олександр Янк

Це більш чітке рішення, ніж встановлення додаткового слухача, щоб просто отримувати кліки.
Мікрос

цей код краще працював для мене `var target = $ (напр. ціль); якщо (! target.is ("span")) повернутися; `
Cr1xus

17

Кращий спосіб за допомогою () з ланцюжком, як,

$(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тому галерея закриється лише тоді, коли ви клацнете в області зів'ялого чорного фону, але не тоді, коли ви натиснете в області вмісту. Це можна застосувати до багатьох різних сценаріїв.


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

2
@ Halcyon991 в будь-якому випадку передається через аргументи, e - це лише посилання
qodeninja

@qodeninja Так, але непотрібне доповнення символів, якщо воно не використовується.
Halcyon991

Немає сенсу додавати return falseпосилання, його слід натискати.
eapo

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").
Френк Форте
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.