3 votes

Inverse du bullage : empêcher le clic sur les enfants du DOM

Je comprends comment le bouillonnement et event.stopPropagation() fonctionne, mais je cherche un moyen d'éviter les gestionnaires de clics sur tous les enfants d'un nœud DOM.

<div onclick="console.log('LOG ME')">
  <div onclick="console.log('DO NOT LOG ME')">Click me</div>
</div>

Je veux que "LOG ME" soit enregistré, mais que "DO NOT LOG ME" ne le soit pas.

J'ai trouvé une solution CSS en utilisant pointer-events: none Cependant, tous mes styles CSS :hover et :focus ont disparu de la division enfant.

Des idées ?

Edit : Un peu de contexte. J'utilise React. Le div extérieur est un HOC, le div intérieur est un composant visible. Je veux que le HOC attrape tous les clics du composant enfant, et arrête la propagation du clic dans l'enfant. Dans React, je le ferais :

const HOC = ChildComponent => class extends Component {
  handleClick = event => { /* Do what with event? */ }

  render() {
    return <div onClick={this.handleClick}>
      <ChildComponent />
    </div>;
  }
}

ChildComponent est un composant cliquable

2voto

Gaby aka G. Petrioli Points 85891

Mise à jour (pour la question mise à jour)

Si vous utilisez react, utilisez l'option Capture à la fin de l'événement pour que le gestionnaire soit déclenché lors de la phase de capture. (Voir https://reactjs.org/docs/events.html#supported-events )

Donc quelque chose comme

const HOC = ChildComponent => class extends Component {
  handleClick = event => { 
     /* Do what with event? */
     event.stopPropagation();
     /*the rest of the code you want for handling the click*/
  }

  render() {
    return <div onClickCapture={this.handleClick}>
      <ChildComponent />
    </div>;
  }
}

Vous devez arrêter la propagation sur l'événement, et vous devez utiliser la phase de capture de l'événement, et non la bulle.

Ainsi, au lieu d'utiliser le onclick utiliser le la bonne façon d'attacher les gestionnaires d'événements et pour l'extérieur qui doit être le conteneur, utilisez true comme 3ème paramètre ( le site useCapture paramètre )

document.querySelector('.outer').addEventListener('click', function(e){
  e.stopPropagation();
  console.log('LOG ME')
}, true);

document.querySelector('.inner').addEventListener('click', function(e){
  console.log('DO NOT LOG ME')
}, false);

<div class="outer">
  <div class="inner">Click me</div>
</div>

0voto

Scott Marcus Points 45

Vous pourriez utiliser la phase de capture de l'événement pour vous brancher sur le clic au niveau du parent et arrêter la propagation vers les enfants.

Vous devez également suivre normes modernes pour l'enregistrement des événements y ne pas utiliser les attributs d'événements HTML en ligne .

// Normally, the following would set up event handler that bubbles up through all div elements
// but, you will see that it only fires once, for the parent element...
document.querySelector("div").addEventListener("click", function(evt){

    console.log(this);
    evt.stopPropagation();  // Don't allow the event

  }, true); // Adding the 3rd argument of true causes the event handler to be registered during the capture phase

<div class="parent">
  <div class="child">Click me</div>
</div>

0voto

charlietfl Points 41873

Cela peut s'appliquer ou non à votre situation, mais compte tenu de l'exemple de l'imbrication des inline onclick vous pouvez supprimer les éléments imbriqués onclick et le gestionnaire d'événement ne sera pas appelé.

[].slice.call(document.querySelectorAll('[onclick] [onclick]')).forEach(function(el) {
    el.removeAttribute('onclick')
})

<div onclick="console.log('LOG ME')">
  <div onclick="console.log('DO NOT LOG ME')">Click me</div>
</div>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X