#javascript #jquery #loops
#javascript #jquery #циклы
Вопрос:
у меня есть этот код, который работает без каких-либо проблем:
<script>
$(document).ready(function () {
$(".block1").click(function () {
$("#fade1").fadeIn("slow").fadeOut("slow");
});
});
$(document).ready(function () {
$(".block2").click(function () {
$("#fade2").fadeIn("slow").fadeOut("slow");
});
});
</script>
Однако, поскольку у меня есть шесть блоков, я пытаюсь изменить его на цикл:
$(document).ready(function () {
for (i=1; i<7; i ) {
alert(i);
$(".block" i).click(function () {
$("#fade" i).fadeIn("slow").fadeOut("slow");
alert (i);
});
}
});
Этот цикл for работает не так, как ожидалось. Он выдает предупреждение всем 6 блокам, как и ожидалось, но вместо каждого предупреждения с надписью «block1», «block2», «block3» и т.д., Все они говорят «block7».
Кто-нибудь знает, почему это происходит?
Ответ №1:
Если вы добавите общий класс в свои divs, вы могли бы сделать это без цикла.
Обновить:
Не на 100% понятно, что вы пытаетесь сделать, но вот метод, который мог бы работать с использованием данных jquery.
<div class="animate-block" data-fadeid="fade1"></div>
<div class="animate-block" data-fadeid="fade2"></div>
<div class="animate-block" data-fadeid="fade3"></div>
<div class="animate-block" data-fadeid="fade4"></div>
<div id="fade1"></div>
<div id="fade2"></div>
<div id="fade3"></div>
<div id="fade4"></div>
<script>
$(document).ready(function () {
$(".animate-block").click(function () {
var fadeId = $(this).data("fadeid");
$("#" fadeId).fadeIn("slow").fadeOut("slow");
});
});
</script>
Если ваши блочные и затухающие разделы находятся рядом друг с другом, это становится еще проще, поскольку вы можете использовать метод next().
<div class="animate-block"></div>
<div id="fade1"></div>
<div class="animate-block"></div>
<div id="fade2"></div>
<div class="animate-block"></div>
<div id="fade3"></div>
<div class="animate-block"></div>
<div id="fade4"></div>
<script>
$(document).ready(function () {
$(".animate-block").click(function () {
$(this).next().fadeIn("slow").fadeOut("slow");
});
});
</script>
Комментарии:
1. Это не отвечает на его вопрос. Он хочет, чтобы у каждого предупреждения было другое сообщение — от «1» до «6».
2. Это всегда исчезает
#fade1
каждый раз, не"#fade" i
.
Ответ №2:
Вам нужно создать замыкание для захвата текущего значения i
, чтобы при i
увеличении оно не влияло на предыдущие вызовы. Что-то вроде этого:
$(document).ready(function() {
for (var i = 1; i < 7; i ) {
alert(i);
$(".block" i).click(doIt(i));
}
function doIt(i){
return function(){
alert(i);
}
}
});
PS: Не стесняйтесь кричать на меня, если я использовал термин closure
неправильно.
Ответ №3:
Вместо того, чтобы присваивать каждому элементу разное имя класса и добавлять номер, чтобы найти тот, который вы ищете, просто присвойте им всем одно и то же имя класса:
$(document).ready(function(){
$(".block").click(function(){
$(this).children(".fade").fadeIn("slow").fadeOut("slow");
alert($(".block").index(this)); //gets the block index
});
});
Ответ №4:
но когда я нажимаю кнопку, мне всегда выдается 7 в оповещении.
Я не совсем уверен, что вы здесь имеете в виду, но вы имеете в виду, что второе предупреждение всегда отображает «7»? Если это так, то это потому, что ваши onclick
функции захватили переменную i
. Вы не записываете копию i
, но вместо этого каждая функция записывает ссылку на нее. Итак, к моменту нажатия кнопки он имеет значение 7
.
Ответ №5:
Причина, по которой это происходит, заключается в том, что «i» — это переменная, которая сохраняется после настройки всех функций .click. Это означает, что после завершения вашего цикла значение i будет равно 7. Когда вы нажимаете на блок и активируете его функцию оповещения, в оповещении используется значение i в данный момент времени, которое всегда равно 7, потому что цикл уже завершен.
Ответ №6:
Ваша проблема в том, что ваша функция click использует глобальное значение i
(7), а не статическое значение с момента подключения функции.
Вы хотите привязать текущее значение i к функции click. Есть несколько способов сделать это. Проще всего создать статическую функцию. Попробуйте:
$(document).ready(function () {
for (var i=1; i<7; i ) {
alert(i);
var click_func = new Function(
"$('#fade" i "').fadeIn('slow').fadeOut('slow');
alert(" i ");");
$(“.block” i).click(click_func);
}
});
Комментарии:
1. Разве
new Function(
в принципе это не простоeval
и не отличная идея?2. Он более ограничен, чем eval, поскольку может быть создано только тело функции. Поскольку OP хотел использовать концепцию метапрограммирования в цикле, я чувствую, что это самое простое решение. Альтернативы включают в себя: 1) создание замыкания для сохранения копии i, как вы и Роб W продемонстрировали. или 2) Добавьте свойство i к объекту функции.
Ответ №7:
Это потому, что к моменту запуска вашего события цикл завершен, и все они используют последнее значение в i, а не то значение, которое было при регистрации события.
Это должно работать для селектора,
$(".block" i).click(function ()
Это должно быть генерацией «block1», «block2» и т.д. И назначением события.
$("#fade" i).fadeIn("slow").fadeOut("slow");
alert (i);
однако все эти строки используют i
и i
остаются активными как clojure, и i присваивается от 1 до 7, и к моменту запуска вашего события i = 7, поэтому каждый раз, когда вы нажимаете «.block1» и т.д., Он будет только исчезать #fade7 и выводить alert (7).
Попробуйте это как :
$(document).ready(function () {
for (i=1; i<7; i ) {
alert(i);
(function (i) {
$(".block" i).click(function () {
$("#fade" i).fadeIn("slow").fadeOut("slow");
alert (i);
});
})();
}
});