Tengo dos botones en mi página que uso para probar cosas nuevas. Ambos usan el "onclick" vinculado a una función JS diferente. ¿Por alguna razón el segundo activa ambos? Y no puedo entender lo que he hecho mal.
El HTML se ve así:
<!DOCTYPE html> <html> <head> <link HREF="styleTest.css" rel="stylesheet"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Roboto+Serif:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet"> <script type="text/javascript" src="script.js"></script> <title>TEST</title> </head> <body> <div class="page"> <div class="nav-container" onclick="hamburger(this)"> <div class="ham-container"> <div class="hamburger-1"></div> <div class="hamburger-2"></div> <div class="hamburger-3"></div> </div> <div class="nav-bar"> <a>Home</a> <a>Services</a> <a>About</a> <a>Projects</a> </div> <div class="button-test"> <button onclick="clickTest()">CLICK ME</button> <h1>Test text</h1> </div> </div> </body>Y las dos funciones JS:
function hamburger(x) { x.classList.toggle("change"); } var i =0 function clickTest() { i++; console.log(i) }¿Qué estoy haciendo mal?
Cuando activa un evento en un elemento, se activará secuencialmente para su padre, para su abuelo... hasta el último elemento principal. A menudo no vemos que suceda este comportamiento porque a menudo tenemos un oyente de eventos en la familia de elementos.
Pero si el elemento activado está dentro de un padre que tiene un detector de eventos para el mismo evento, como en su caso, ambos se activarán. Sin embargo, puede evitar este comportamiento con la ayuda del método stopPropagation , de esta manera:
function clickTest(e) { e.stopPropagation(); i++; console.log(i) }La forma en que funcionan los detectores de eventos es que cuando tiene un objeto anidado (por ejemplo, un botón dentro de un div) y ambos tienen detectores de eventos, cuando hace clic en el elemento interno (botón), el detector de eventos del button se activará primero antes el detector de eventos principal
Para resolver esto, debe detener la propagación usando este código
<button onclick="clickTest(event)">CLICK ME</button>y el guion
function clickTest(e) { e.stopPropagation(); i++; console.log(i) }Esto sucede debido a un concepto conocido como Bubbling en DOM.
Cuando ocurre un evento en un elemento, primero ejecuta los controladores en él, luego en su padre y luego en otros ancestros.
Intente jugar con este fragmento a continuación.
<style> body * { margin: 10px; border: 1px solid blue; } </style> <form onclick="alert('form')">FORM <div onclick="alert('div')">DIV <p onclick="alert('p')">P</p> </div> </form> Un clic en el <p> interno primero ejecuta onclick:
En eso <p> .
Luego en el exterior <div> .
Luego, en el <form> externo.
Y así sucesivamente hacia arriba hasta el objeto del documento.
Consulte esta página para mayor claridad: Enlace