Tengo un elemento principal con varios elementos secundarios, algunos de los cuales tienen sus propios detectores de eventos y otros no. El elemento principal tiene un controlador de clics que deseo ejecutar solo si hago clic en el elemento principal y no en ninguno de los elementos secundarios.
document.getElementById('parent').addEventListener('click', ()=> console.log('parent clicked')) document.getElementById('child2').addEventListener('click', ()=> console.log('child2 clicked')) #parent { height: 300px; width: 300px; background-color: Lightgreen; wrap: true; display: flex; flex-direction:column; gap: 20px; padding: 50px 50px; } #parent * { height: 100px; width: 100px; background-color: white; text-align: center; display: grid; place-items: center; } <div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else- <div id="child1">child1 <br> -Nothing should happen when clicked-</div> <div id="child2">child2 <br> -Should only log -child 2 if clicked-</div> </div> stopPropagation() , funciona para detener el burbujeo del evento, pero necesitaría agregarlo a todos los controladores de eventos secundarios, y todavía no puedo evitar que el padre se dispare al hacer clic en objetos sin detectores de eventos.
¿Hay alguna forma de restringir el controlador principal solo al hacer clic en el elemento en sí?
event.currentTarget podría ser útil para verificar que el evento proviene de ese elemento específico en el que configuraste el evento, no de un elemento secundario. Una definición rápida de la documentación de MDN:
La propiedad de solo lectura
currentTargetde la interfazEventidentifica el destino actual del evento, ya que el evento atraviesa el DOM. Siempre hace referencia al elemento al que se ha adjuntado el controlador de eventos, a diferencia deEvent.target, que identifica el elemento en el que se produjo el evento y que puede ser su descendiente.
Y la ventaja de hacerlo en la solución de @CertainPerformance (que es genial) es que no tienes que conocer ese elemento.
document.getElementById('parent').addEventListener('click', (e)=> { if(e.currentTarget===e.target){ console.log('parent clicked'); } }); document.getElementById('child2').addEventListener('click', (e)=> { if(e.currentTarget===e.target){ console.log('child2 clicked'); } }); #parent { height: 300px; width: 300px; background-color: Lightgreen; wrap: true; display: flex; flex-direction:column; gap: 20px; padding: 50px 50px; } #parent * { height: 100px; width: 100px; background-color: white; text-align: center; display: grid; place-items: center; } <div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else- <div id="child1">child1 <br> -Nothing should happen when clicked-</div> <div id="child2">child2 <br> -Should only log -child 2 if clicked-</div> </div>Esta es solo una pequeña adición a esta respuesta , y no pretende ser una respuesta. Evento con e.currentTarget === e.target un clic en un elemento secundario podría desencadenar un parent clicked si pointer-events: none se utiliza en el elemento secundario.
Pero si pointer-events: none se usa, entonces no puede hacer nada al respecto de todos modos, ya que dice explícitamente que este elemento debe ignorarse para el manejo de eventos.
document.getElementById('parent').addEventListener('click', (e) => { if (e.currentTarget === e.target) { console.log('parent clicked'); } }); #parent { height: 300px; width: 300px; background-color: Lightgreen; wrap: true; display: flex; flex-direction: column; gap: 20px; padding: 50px 50px; } #parent * { height: 100px; width: 100px; background-color: white; text-align: center; display: grid; place-items: center; } [data-no-pointer-event] { pointer-events: none; } <div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else- <div id="child1">child1 <br> - Nothing should happen when clicked -</div> <div id="child2" data-no-pointer-event>child 2 - will log parent clicked - </div> </div>Verifique si el .target es el principal; si lo es, eso significa que el clic fue directamente en el principal y no es un evento que brota de un secundario.
const parent = document.getElementById('parent'); parent.addEventListener('click', (e) => { if (e.target === parent) { console.log('parent clicked'); } }); document.getElementById('child2').addEventListener('click', () => console.log('child2 clicked')) #parent { height: 300px; width: 300px; background-color: Lightgreen; wrap: true; display: flex; flex-direction: column; gap: 20px; padding: 50px 50px; } #parent * { height: 100px; width: 100px; background-color: white; text-align: center; display: grid; place-items: center; } <div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else- <div id="child1">child1 <br> -Nothing should happen when clicked-</div> <div id="child2">child2 <br> -Should only log -child 2 if clicked-</div> </div>