¿Cómo evito que se active el evento onclick de un padre cuando se hace clic en un ancla secundaria?

Resuelto Jonathon Watney asked hace 15 años • 26 respuestas

Actualmente estoy usando jQuery para hacer que se pueda hacer clic en un div y en este div también tengo anclajes. El problema con el que me encuentro es que cuando hago clic en un ancla, ambos eventos de clic se activan (para el div y el ancla). ¿Cómo evito que se active el evento onclick del div cuando se hace clic en un ancla?

Aquí está el código roto:

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.example">I don't want #clickable to handle this click event.</a>
</div>
Jonathon Watney avatar Sep 03 '09 00:09 Jonathon Watney
Aceptado

Los eventos se expanden hasta el punto más alto del DOM en el que se ha adjuntado un evento de clic. Entonces, en su ejemplo, incluso si no tuviera ningún otro elemento explícitamente en el que se pueda hacer clic en el div, cada elemento secundario del div expandiría su evento de clic en el DOM hasta que el controlador de eventos de clic del DIV lo detecte.

Hay dos soluciones para esto: verificar quién realmente originó el evento. jQuery pasa un objeto eventargs junto con el evento:

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

También puede adjuntar un controlador de eventos de clic a sus enlaces que les indique que dejen de difundir eventos después de que se ejecute su propio controlador:

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});
Rex M avatar Sep 02 '2009 17:09 Rex M

Utilice el método stopPropagation , vea un ejemplo:

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

Como dice jQuery Docs:

stopPropagationEl método evita que el evento se propague en el árbol DOM, evitando que los controladores principales sean notificados del evento.

Tenga en cuenta que no impide que otros oyentes manejen este evento (por ejemplo, más de un controlador de clic para un botón); si no es el efecto deseado, debe usarlo stopImmediatePropagationen su lugar.

Cleiton avatar Sep 02 '2009 17:09 Cleiton

Aquí mi solución para todos los que buscan un código que no sea jQuery (javascript puro)

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

Su código no se ejecutará si se hace clic en los hijos de los padres.

Sabaz avatar Apr 07 '2015 18:04 Sabaz

Si no tiene la intención de interactuar con los elementos internos en ningún caso , entonces una solución CSS podría resultarle útil.

Simplemente configure los elementos internos enpointer-events: none

en tu caso:

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

o para apuntar a todos los elementos internos en general:

.clickable * {
    pointer-events: none;
}

Este sencillo truco me ahorró mucho tiempo mientras desarrollaba con ReactJS.

La compatibilidad con el navegador se puede encontrar aquí: http://caniuse.com/#feat=pointer-events

Hooman Askari avatar May 04 '2017 09:05 Hooman Askari