2012-04-09 5 views
0

прежде чем все, за помощь и извините за вопрос о нобе., когда я нажму, это последнее возможное значение

У меня проблема с событием внутри a for. DOM нечто подобное:

<div class="wrap"> 

    <div class="trigger">...</div> 
    <div class="trigger">...</div> 

    <div class="box">...</div> 
    <div class="box">...</div> 

</div> 

И мой JS JQuery является:

for(i = 0; i < $('.trigger').length; i++){ 
$('.trigger:eq('+i+')').click(function(){ 
    $('.box:eq('+i+')').fadeIn(); 
}); 

$('.box:eq('+i+') .bt-close').click(function(){ 
    $('.box:eq('+i+')').fadeOut(); 
}); 
} 

Ну, проблема в том, когда я нажимаю на спусковой крючок, значение I равно 2. Я не хотите использовать trigger1, trigger2 ... потому что я не знаю, сколько из них будет иметь в финальной версии.

+0

Популярная вопрос, заданный в другой форме. i ссылается, а не назначается. – epascarello

+0

d2dbr Вы могли бы указать четкий вопрос?Я даже не знаю, в чем вопрос. – nolabel

ответ

4
function createEffects(index) { 
    $('.trigger:eq(' + index + ')').click(function() { 
     $('.box:eq(' + index + ')').fadeIn(); 
    }); 

    $('.box:eq(' + index + ')').click(function() { 
     $('.box:eq(' + index + ')').fadeOut(); 
    }); 
} 


for (i = 0; i < $('.trigger').length; i++) { 

    createEffects(i); 
}​ 

Я бы не стал использовать закрытие, когда сможешь. Вот пример без них: http://jsfiddle.net/JBbQk/

+0

Любопытно, не могли бы вы объяснить, какая разница между вызовом функции из цикла for и просто с содержимым функции внутри цикла for? –

+2

По мере продвижения цикла каждое событие click по-прежнему указывает на ту же переменную 'i'. Поскольку события щелчка будут запускаться после завершения цикла, все они укажут на последнее значение, которое было сохранено в i. Когда вы завершаете свою логику в функции, вы создаете новую копию 'i' для каждой функции для ссылки, которая фиксирует текущее значение' i'. –

+0

Спасибо за ответ. Теперь это работает, и решение прост. Благодарю. – d2dbr

1

Проблема в закрытии. Функция внутри цикла будет помнить переменную i из области вокруг нее, а не ее значение. Когда функция вызывается, цикл уже выйдет, а значение переменной будет последним. Вместо этого, чтобы функции сами получали значение. Обычный способ сделать это - использовать другую переменную. Один из способов сделать это - шоу @JoeTuskan. Другой заключается в использовании самостоятельного выполнения анонимной функции:

for(i = 0; i < $('.trigger').length; i++){ 
    (function(j) { 
    $('.trigger:eq('+j+')').click(function(){ 
     $('.box:eq('+j+')').fadeIn(); 
    }); 

    $('.box:eq('+j+') .bt-close').click(function(){ 
     $('.box:eq('+j+')').fadeOut(); 
    }); 
    })(i); 
} 

Разница здесь в том, что внешняя анонимная функция (один сразу оборачивать содержимое цикла) не имеет доступа к переменной цикла на всех, и поэтому не захватывает Это. Вместо этого он вызывается с параметром, значение которого не изменяется внутри функции, которое затем захватывается внутренними функциями.

Не совсем то, что вы не должны создавать функции внутри циклов; но если вы это сделаете, вы хотите иметь замыкание, которое захватывает переменную цикла между ними и циклом. Является ли функция, создающая это закрытие внешне определяемой, как в примере @ JoeTuskan, или внутренняя, как у меня, является вопросом стиля; пока вы понимаете, почему он работает так, как он. На самом деле способ, объясненный в его сообщении, должен быть немного быстрее, чем этот, так как таким образом вы продолжаете создавать N анонимных функций, но я считаю, что было бы легче понять, что на самом деле происходит именно так.

+0

+1 для фактического объяснения этого. –

0

Причина такого поведения заключается в том, что эти function(){...} являются замыканиями. Короче говоря, когда вы создаете закрытие, интерпретатор javascript копирует среду в точке объявления функции, тем самым позволяя функции доступа к ним, даже если они выходят за рамки (и будут собираться мусором без закрытия).

Вы столкнулись с одним из возможных недостатков этого: замыкания не получают копии объектов, они просто имеют доступ к переменным. Рассмотрим пример:

var i=0; 
var closure = function() {alert(i);} 
closure(); //alerts 0 
i=1; 
closure(); //alerts 1; 

То же самое происходит в вашем примере. За цикл работает до конца, оставив i с $('.trigger').length значением.

Таким образом, правильный способ достижения того, что вы хотите Joe Tuskan's answer

0

Другой способ сделать это с помощью каждого из них:

var triggers = $('.trigger'); 
var boxes = $('.box'); 
triggers.each(
    function(ind){ 
     var box = boxes.eq(ind); 
     $(this).on("click", 
      function(){ 
       box.fadeIn(); 
      } 
     ); 
    } 
); 

boxes.find(".bt-close").on("click", 
    function(){ 
     $(this).closest('.box').fadeOut(); //might be better to use parents(".box") - depends on HTML 
    } 
); 
Смежные вопросы