¿Cómo agregar oyentes de eventos individuales usando jquery .each ()?
Tengo una configuración simple: dos botones con diferentes valores. Quiero usar la función .each () de jquery para agregar un detector de eventos de clic a cada uno de los botones que simplemente registra los valores de cada botón. Pero de alguna manera, cuando se usa .each (), jquery sobrescribe el controlador de clic de los botones anteriores. Esto me deja con dos preguntas:
- ¿Porqué es eso?
- ¿Cómo agrego oyentes de eventos individuales a una colección de objetos jquery?
Ver código a continuación
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => { $(`button[toggle]`).each((_, button) => {
let $toggle = $(button);
type = $toggle.attr("type"); value = $toggle.attr("value");
$toggle.on("click", () => {
console.log(type, value);
});
});
});
</script>
</head>
<body>
<div>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
</div>
</body>
</html>
Respuestas
El problema en su código es porque ha declarado implícitamente las variables type
y value
, por lo que están dentro del window
alcance. Como tal, cada iteración siguiente sobrescribe los valores para que solo se vean los valores finales después de que finalice el ciclo.
Para solucionar esto, defina las variables dentro del ciclo:
$(() => { $(`button[toggle]`).each((_, button) => {
let $toggle = $(button);
let type = $toggle.attr("type"); let value = $toggle.attr("value");
$toggle.on("click", () => {
console.log(type, value);
});
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<div>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
</div>
Sin embargo , no necesita eleach()
bucle en absoluto. Puede solucionar el problema y mejorar la calidad del código vinculando el mismo controlador de eventos a todos losbutton
elementos y utilizando latarget
propiedad del evento que se genera para acceder a sus atributos.
Además, tenga en cuenta que agregar sus propios atributos no estándar, toggle
en este caso, puede generar problemas en la interfaz de usuario y JS. Un mejor enfoque es usar una clase para agrupar los elementos.
Finalmente, one
y two
no son valores válidos para el type
atributo. En su lugar, utilice un data
atributo para adjuntar sus propios metadatos personalizados a un elemento.
Con todo lo dicho, intente esto:
jQuery($ => {
$('.toggle').on('click', e => { let $toggle = $(e.target); let type = $toggle.data("type");
let value = $toggle.prop("value");
console.log(type, value);
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<div>
<button class="toggle" data-type="one" value="true">One</button>
<button class="toggle" data-type="two" value="false">Two</button>
</div>
usar $(this)
dentro de la devolución de llamada de clic
$(() => {
$(`button[toggle]`).each((_, button) => { $(button).on("click", function(){
type = $(this).attr("type"); value = $(this).attr("value");
console.log(type, value);
});
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
Y tampoco es necesario mencionar dentro de cada devolución de llamada. Podrías llamar de forma normal como a continuación.
$(() => { $(`button[toggle]`).on("click", function(){
type = $(this).attr("type"); value = $(this).attr("value");
console.log(type, value);
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
- Porque el oyente se une al último valor de $ toggle.
- Creando y ejecutando una nueva función como se muestra en el fragmento.
Explicado mejor en esta pregunta .
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => {
$(`button[toggle]`).each((_, button) => { let $toggle = $(button); type = $toggle.attr("type");
value = $toggle.attr("value"); $toggle.on("click", ((type, value) => {
return () => {
console.log(type, value);
};
})(type, value));
});
});
</script>
</head>
<body>
<div>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
</div>
</body>
</html>