Для цикла не работает на селекторе Jquery

0

Борясь с циклом for... Я не могу заставить его работать. Попытайтесь добавить цикл for к элементу (".circle" + (i + 1)), но не скрывать и исчезать в одном круге (i). Возможно ли это или какой-то подобный подход?

Любая помощь была бы оценена!

<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<ul class="menu">
  <li class="first"><a href="#btn1">btn1</a></li>
  <li class="second"><a href="#btn2">btn2</a></li>
  <li class="third"><a href="#btn3">btn3</a></li>
  <li class="forth"><a href="#btn4">btn4</a></li>
</ul>

<div class="circle1 circle">1</div>
<div class="circle1 circle">2</div>
<div class="circle1 circle">3</div>
<div class="circle4 circle">4</div>

<script>
for(i=0;i<$(".menu li").length;i++){
    $(".menu li").eq(i).on('click',function(){
      $(".circle").hide();
      $('.circle'+(i+1)).stop().fadeIn('300');
      return false;
    });
  }
</script>
</body>
</html>
  • 0
    Краткий ответ: замыкания. i всегда равен его значению в конце цикла в вашем обработчике кликов.
Теги:
for-loop
selector

2 ответа

4

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

for(i=0;i<$(".menu li").length;i++){
    (function(j) {
        $(".menu li").eq(j).on('click',function(){
            $(".circle").hide();
            $('.circle'+(j+1)).stop().fadeIn('300');
            return false;
        });
    })(i);
}

То, что было сделано выше, создает замыкание с помощью Expression Expression Expression (IIFE), которое создает новую область и копирует значение i во время цикла.

Также было бы назначить $(".menu li").length переменной перед циклом, чтобы jQuery не воссоздавал коллекцию каждый раз, когда она циклы.

Чтобы понять, что происходит, сравните это:

for(i=0;i<5;i++){
    setTimeout(function() {
        console.log(i);
    },100);
}

// outputs: 5 5 5 5 5

К этому:

for(i=0;i<5;i++){
    (function(i) {
        setTimeout(function() {
            console.log(i);
        },100);
    })(i);
}

// outputs: 0 1 2 3 4

http://jsfiddle.net/PLsUN/

0

Ответ Мэтта Берланда правильный и очень тщательный. Это просто альтернативное предложение избегать использования цикла for (если вы предпочитаете):

// Use the jQuery already-available '.each' method
$(".menu li").each(function(index, list_element){

    (function(list_index){ // as per Matt answer
        list_element.on('click',function(){
            $(".circle").hide();
            $('.circle'+(list_index+1)).stop().fadeIn('300');
            return false;
        }
    })(index);

});

Эффект тот же, и нет разницы в производительности (насколько я знаю); Я нахожу его немного чище.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню