Как добавить отдельных прослушивателей событий с помощью jquery .each ()?
У меня простая настройка: две кнопки с разными значениями. Я хочу использовать функцию .each () из jquery, чтобы добавить прослушиватель событий щелчка к каждой из кнопок, который просто регистрирует значения каждой кнопки. Но каким-то образом при использовании .each () jquery перезаписывает обработчик кликов для предыдущей кнопки (кнопок). Это оставляет мне два вопроса:
- Это почему?
- Как добавить отдельных прослушивателей событий в коллекцию объектов jquery?
См. Код ниже
<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>
Ответы
Проблема в вашем коде, потому что вы неявно объявлять type
и value
переменные, поэтому они находятся в window
области видимости. Таким образом, каждая следующая итерация перезаписывает значения, так что после завершения цикла видны только конечные значения.
Чтобы исправить это, определите переменные внутри цикла:
$(() => { $(`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>
Однако вам вообще не нуженeach()
цикл. Вы можете исправить проблему и улучшить качество кода, привязав один и тот же обработчик событий ко всемbutton
элементам и используяtarget
свойство события, которое возникает для доступа к их атрибутам.
Кроме того, обратите внимание, что добавление собственных нестандартных атрибутов toggle
в этом случае может привести к проблемам в пользовательском интерфейсе и JS. Лучше всего использовать класс для группировки элементов.
Наконец, one
и two
недопустимые значения для type
атрибута. data
Вместо этого используйте атрибут, чтобы прикрепить свои собственные метаданные к элементу.
С учетом всего сказанного попробуйте следующее:
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>
использовать $(this)
внутри обратного вызова клика
$(() => {
$(`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>
А также не нужно упоминать внутри каждого обратного вызова. Вы можете позвонить обычным способом, как показано ниже
$(() => { $(`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>
- Поскольку слушатель привязывается к последнему значению $ toggle.
- Создав и запустив новую функцию, как показано во фрагменте.
Объясните лучше в этом вопросе .
<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>