код не работал в режиме цикла

#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 увеличении оно не влияло на предыдущие вызовы. Что-то вроде этого:

http://jsfiddle.net/UD5sf/

 $(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);
            });
        })();
    }
});