Переменные в цикле - PullRequest
       3

Переменные в цикле

1 голос
/ 13 января 2012
carousel: function(){
            var $carouselCr = $('#carousel'),
                $tabCr = $('.carouselTabs', $carouselCr),
                $itemCr = $('.carouselContents', $carouselCr),
                tabAmount = (function(){
                    if($('a', $tabCr).length === $('.item', $itemCr).length){
                        return $('a', $tabCr).length;
                    }else{
                        throw "error: verschillend aantal tabs vs items";
                    }               
                })();

            var i = tabAmount;
            while(i--){                                     
                var item = $($('.item', $itemCr)[i]),
                    tab = $($('a', $tabCr)[i]);
                console.log(item, tab);
                $(tab).click(function(){
                    $('.item', $itemCr).hide();
                    $(item).show();
                })

            }

        }

Как видите, я пытаюсь прикрепить событие клика к каждой «вкладке», чтобы выбрать каждый «элемент». Я делаю что-то не так. Все вкладки относятся к первому элементу.

Если я войду $('.item', $itemCr)[i] в цикл, он вернет все различные элементы, а не только первый.

Упрощенная структура HTML

<div id="carousel" class="block">
    <div class="carouselTabs">
        <a href="#">
        </a>
    <!-- repeating -->
    </div>
    <div class="carouselContents">                      
        <div class="item">
        </div>  
    <!-- repeating -->                  
    </div>
</div>

Ответы [ 2 ]

3 голосов
/ 13 января 2012

Цикл не создает новую область видимости переменной.Вам нужно создать обработчик щелчков в отдельной функции и передать в эту функцию все, что нужно для области действия.

 // creates the handler with the scoped item, and returns the handler
function create_handler(this_item) {
    return function () {
        $('.item', $itemCr).hide();
        $(this_item).show();
    };
}

var i = tabAmount;
var a_els = $('a', $tabCr);
var items = $('.item', $itemCr);
while (i--) {
    var item = items[i],
        tab = a_els[i];
    $(tab).click( create_handler(item) );
}

Также обратите внимание, что вам не следует делать выбор DOM в цикле,Кэшируйте его один раз вне цикла и ссылайтесь на него в цикле, как я делал выше.


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

carousel: function(){
    var $carouselCr = $('#carousel'),
        $tabCr = $('.carouselTabs', $carouselCr),
        $itemCr = $('.carouselContents', $carouselCr),
        $items = $('.item', $itemCr),
        $a_els = $('a', $tabCr);

    if($a_els.length !== $items.length)
        throw "error: verschillend aantal tabs vs items";

    $a_els.each(function(i) {
        $(this).click(function() {
            $items.hide();
            $items.eq(i).show();
        });
    });
}

Теперь каждый обработчик .click() ссылается на уникальный i, который является индексом текущего элемента $a_els в итерации.

Так, например, когда происходит щелчок по $a_els по индексу 3, $items.eq(i).show(); покажет элемент $items, который также имеет индекс 3.


Другойподход заключается в использовании делегирования событий, когда вы помещаете обработчик в контейнер и предоставляете селектор, чтобы определить, следует ли вызывать обработчик.

Если вы используете jQuery 1.7 или более позднюю версию, вы должны использовать .on() ...

carousel: function(){
    var $carouselCr = $('#carousel'),
        $tabCr = $('.carouselTabs', $carouselCr),
        $itemCr = $('.carouselContents', $carouselCr),
        $a_els = $('a', $tabCr),
        $items = $('.item', $itemCr);

    if($a_els.length !== $items.length)
        throw "error: verschillend aantal tabs vs items";

    $tabCr.on('click','a',function() {
        var idx = $a_els.index( this ); // get the index of the clicked <a>
        $items.hide();
        $items.eq(idx).show(); // ...and use that index to show the content
    });
}

Или до jQuery 1.7 вы бы использовали .delegate() ...

carousel: function(){
    var $carouselCr = $('#carousel'),
        $tabCr = $('.carouselTabs', $carouselCr),
        $itemCr = $('.carouselContents', $carouselCr),
        $a_els = $('a', $tabCr),
        $items = $('.item', $itemCr);

    if($a_els.length !== $items.length)
        throw "error: verschillend aantal tabs vs items";

    $tabCr.delegate('a','click',function() {
        var idx = $a_els.index( this ); // get the index of the clicked <a>...
        $items.hide();
        $items.eq(idx).show(); // ...and use that index to show the content
    });
}

Таким образом, к $tabCr привязан только один обработчикконтейнер.Он проверяет, соответствует ли выбранный элемент селектору 'a', и, если это так, вызывает обработчик.

Если между элементами <a>...</a> или <div class="item">...</div> есть другие элементы, так чтоиндексы, естественно, не совпадают, нам нужно немного подправить вызов .index().

1 голос
/ 13 января 2012

, чтобы упростить ваш код и сделать его более производительным, вы можете использовать метод делегата

$('.carouselTabs', '#carousel').delegate('a', 'click', function(){

  var ind = $('.carouselTabs a').index(this);
  $('.item', '#carousel').hide().eq(ind).show();

  return false;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...