Tengo un problema con el evento de clic que se recibe en el elemento secundario en lugar del elemento principal. En este momento, el evento de clic está ocurriendo en el elemento de span en lugar del elemento de enlace.
Busqué algunas preguntas SO similares y descubrí EventBubling y cómo prevenirlo, pero desafortunadamente, no funcionó para mí.
HTML
<div class="container"> <div class="list"> <a href="#" data="data-1"> <span>Text 1</span> </a> </div> <div class="list"> <a href="#" data="data-2"> <span>Text 2</span> </a> </div> <div class="list"> <a href="#" data="data-3"> <span>Text 3</span> </a> </div> </div>JS
const list = document.querySelectorAll('.list > a'); Array.from(list).forEach((el) => el.addEventListener('click', (e) => { //e.preventDefault(); e.stopPropagation(); const dataAttr = e.target.getAttribute('data'); console.log(dataAttr); }) );Utilice e.currentTarget en lugar de e.target .
e.currentTarget.getAttribute('data');Lea también: ¿Cuál es la diferencia exacta entre la propiedad currentTarget y la propiedad de destino en JavaScript?
Como se explica en la respuesta anterior:
targetes el elemento que activó el evento (p. ej., el usuario hizo clic en Blockquote)currentTargetes el elemento al que se adjunta el detector de eventos.
Código de trabajo a continuación
const list = document.querySelectorAll('.list a'); //console.log(list); Array.from(list).forEach((el) => el.addEventListener('click', (e) => { //e.preventDefault(); e.stopPropagation(); const dataAttr = e.currentTarget.getAttribute('data'); console.log(dataAttr); }) ); <div class="list"> <a href="#" data="data-1"> <span>Text 1</span> </a> </div> <div class="list"> <a href="#" data="data-2"> <span>Text 2</span> </a> </div> <div class="list"> <a href="#" data="data-3"> <span>Text 3</span> </a> </div>La propagación funciona de manera diferente a lo que crees.
Lo que desea es obtener siempre la etiqueta .closest() a , independientemente del elemento secundario en el que haya hecho clic. Y luego obtienes su atributo de datos
const list = document.querySelectorAll('.list > a'); Array.from(list).forEach((el) => el.addEventListener('click', (e) => { //e.preventDefault(); e.stopPropagation(); const dataAttr = e.target.closest('a').getAttribute('data'); console.log(dataAttr); }) ); <div class="container"> <div class="list"> <a href="#" data="data-1"> <span>Text 1</span> </a> </div> <div class="list"> <a href="#" data="data-2"> <span>Text 2</span> </a> </div> <div class="list"> <a href="#" data="data-3"> <span>Text 3</span> </a> </div> </div>Dado que los enlaces que está agregando a los controladores de eventos no tienen nada dentro de ellos, excepto el elemento de intervalo, supondré que en realidad no desea evitar los clics en el intervalo. En su lugar, desea saber en qué enlace se hizo clic, incluso si el clic fue realmente en el lapso.
Utilice currentTarget en lugar de target .
currentTarget le dará el elemento al que está vinculado el controlador de eventos en lugar del elemento que realmente recibió el clic.