Come aggiungere listener di eventi individuali usando jquery .each ()?
Ho una configurazione semplice: due pulsanti con valori diversi. Voglio usare la funzione .each () da jquery per aggiungere un listener di eventi clic a ciascuno dei pulsanti che registra semplicemente i valori di ciascun pulsante. Ma in qualche modo quando si utilizza .each (), jquery sovrascrive il gestore dei clic per i pulsanti precedenti. Questo mi lascia con due domande:
- Perché?
- Come si aggiungono singoli listener di eventi a una raccolta di oggetti jquery?
Vedere il codice di seguito
<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>
Risposte
Il problema nel codice è perché hai dichiarato implicitamente le variabili type
e value
, quindi sono window
nell'ambito. Pertanto, ogni iterazione successiva sovrascrive i valori in modo che solo i valori finali vengano visualizzati dopo la fine del ciclo.
Per risolvere questo problema, definire le variabili all'interno 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>
Tuttavia , non è affatto necessario ileach()
ciclo. È possibile risolvere il problema e migliorare la qualità del codice associando lo stesso gestore di eventi a tutti glibutton
elementi e utilizzando latarget
proprietà dell'evento che viene sollevata per accedere ai loro attributi.
Inoltre, tieni presente che l'aggiunta di attributi non standard, toggle
in questo caso, può causare problemi nell'interfaccia utente e JS. Un approccio migliore consiste nell'usare una classe per raggruppare gli elementi.
Infine, one
e two
non sono valori validi per l' type
attributo. Utilizza data
invece un attributo per allegare i tuoi metadati personalizzati a un elemento.
Detto questo, prova questo:
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>
utilizzare $(this)
all'interno del clic di richiamata
$(() => {
$(`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>
E inoltre non c'è bisogno di menzionare all'interno di ogni callback. Puoi chiamare in modo normale come di seguito
$(() => { $(`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>
- Perché l'ascoltatore si lega all'ultimo valore di $ toggle.
- Creando ed eseguendo una nuova funzione come mostrato nello snippet.
Spiegato meglio in questa domanda .
<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>