Назначение обработчиков щелчков в цикле for
у меня есть несколько div #mydiv1
,#mydiv2
,#mydiv3
, ... и хотите назначить им обработчики кликов:
$(document).ready(function(){
for(var i = 0; i < 20; i++) {
$('#question' + i).click( function(){
alert('you clicked ' + i);
});
}
});
но вместо того, чтобы показывать 'you clicked 3'
при нажатии на #mydiv3
(как и для каждого другого щелчка) я получаю 'you clicked 20'
. Что я делаю не так?
6 ответов:
Это распространенная ошибка, чтобы создать застежка на петли в Javascript. Вам нужно иметь какую-то функцию обратного вызова такой:
function createCallback( i ){ return function(){ alert('you clicked' + i); } } $(document).ready(function(){ for(var i = 0; i < 20; i++) { $('#question' + i).click( createCallback( i ) ); } });
Обновление 3 Июня 2016: поскольку этот вопрос все еще получает некоторую тягу, и ES6 также становится популярным, я бы предложил современное решение. Если вы пишете ES6, вы можете использовать
let
ключевое слово, которое делаетi
переменная локальная для цикла вместо глобальный:for(let i = 0; i < 20; i++) { $('#question' + i).click( function(){ alert('you clicked ' + i); }); }
Это короче и понятнее.
чтобы уточнить, i равно 20, потому что событие click не будет запущено до тех пор, пока цикл не закончится.
$(document).ready(function(){ for(var i = 0; i < 5; i++) { var $li= $('<li>' + i +'</li>'); (function(i) { $li.click( function(){ alert('you clicked ' + i); }); }(i)); $('#ul').append($li); } });
вы можете получить с назначением обработчика щелчка один раз (или, по крайней мере, не делая много ненужных замыканий). Поместите все дивы в один класс
mydivs
, тогда:$(document).ready(function(){ $('.mydivs').click(function(){ // Get the number starting from the ID's 6th character // This assumes that the common prefix is "mydiv" var i = Number(this.id.slice(5)); alert('you clicked ' + i); }); });
это смотрит на идентификатор элемента, чтобы получить его номер, используя
slice
строковый метод чтобы удалить начальные буквы.Примечание: может быть лучше использовать
$('#divcontainer').on('click', '.mydivs', function(){
вместо
$('.mydivs').click(function(){
используя on чтобы прикрепить обработчик "click", вы можете использовать данные события для передачи своих данных, например:
for(var i = 0; i < 20; i++) { $('#question' + i).on('click', {'idx': i}, function(e) { alert('you clicked ' + e.data.idx); }); }
// // let's creat 20 buttons // for(var j = 0; j < 20; j++) { $('body').append($('<button/>', {type: 'button', id: 'question' + j, text: 'Click Me ' + j})) } // // Passing data to the handler // for(var i = 0; i < 20; i++) { $('#question' + i).on('click', {'idx': i}, function(e) { console.log('you clicked ' + e.data.idx); }); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Как правило, если вы хотите назначить дескрипторы щелчков для большого количества элементов, вы хотите иметь контейнер (более высокий уровень div), который интерпретирует щелчки для вас, поскольку щелчок всплывает из dom.
<div id="bucket"> <span class="decorator-class" value="3"> ... </div> <script> $(document).ready(function(e){ $("#bucket").live('click', function(){ if(e.target).is('span'){ alert("elementid: " + $(e.target).val()); } } } <script>