Сделать JS более эффективным с помощью цикла for

#javascript #jquery #for-loop

#javascript #jquery #for-цикл

Вопрос:

Я очень новичок в JS и jQuery. Я искал повсюду и пробовал разные методы, чтобы сделать мой код более эффективным. В принципе, у меня есть меню, которое продвигает пользователей вниз по странице. Один раздел моего кода определяет, был ли прокручен конкретный DIV , затем добавляет / удаляет некоторые классы из пары элементов. Поскольку я не уверен, как динамически захватывать теги привязки в области содержимого, я использую соглашение об именовании идентификаторов section-# .

Итак, вместо того, чтобы повторять один и тот же блок кода с измененным только числом, я надеялся, что for цикл поможет сделать мой JS более эффективным, но я не думаю, что у меня это совсем правильно.

Исходный код:

 $(function() {
    $(window).scroll(function() {

        var windowpos = $(window).scrollTop();
        $("#jhscroller-menu li a").removeClass("active");
        $(".jhscroller-menu-prog-dot").removeClass("active");

        if (windowpos >= $("#section-1").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-1"]').addClass("active");
            $('a[href$="#section-1"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-2").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-2"]').addClass("active");
            $('a[href$="#section-2"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-3").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-3"]').addClass("active");
            $('a[href$="#section-3"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-4").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-4"]').addClass("active");
            $('a[href$="#section-4"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-5").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-5"]').addClass("active");
            $('a[href$="#section-5"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-6").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-6"]').addClass("active");
            $('a[href$="#section-6"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-7").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-7"]').addClass("active");
            $('a[href$="#section-7"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-8").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-8"]').addClass("active");
            $('a[href$="#section-8"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-9").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-9"]').addClass("active");
            $('a[href$="#section-9"] .jhscroller-menu-prog-dot').addClass("active");
        }

        if (windowpos >= $("#section-10").offset().top) {
            $("#jhscroller-menu li a").removeClass("active");
            $('a[href$="#section-10"]').addClass("active");
            $('a[href$="#section-10"] .jhscroller-menu-prog-dot').addClass("active");
        }
    });
});
  

Новый код:

 $(function() {
    $(window).scroll(function() {

        var windowpos = $(window).scrollTop();
        $("#jhscroller-menu li a").removeClass("active");
        $(".jhscroller-menu-prog-dot").removeClass("active");

        for (var i = 1; i <= 10; i  ) {
            if (windowpos >= $("#section-"   i).offset().top) {
                $("#jhscroller-menu li a").removeClass("active");
                $('a[href$="#section-"'   i   ']').addClass("active");
                $('a[href$="#section-'   i   '] .jhscroller-menu-prog-dot').addClass("active");
            }
        }
    });
});
  

Вот CodePen рабочего меню, чтобы получить представление о том, чего я пытаюсь достичь.

Комментарии:

1. «Я не думаю, что у меня это совсем правильно»: Пожалуйста, уточните.

2. Вы кое-что потеряли " . Вот что вам следует использовать: 'a[href$="#section-' i '"] (дважды внутри for-if конструкции). Я проголосую за закрытие как «Типографская ошибка».

3. Побочное замечание; Я бы настоятельно рекомендовал вам кэшировать некоторые запросы DOM вне обработчика прокрутки и использовать кэшированные результаты внутри обработчика событий, даже если вам приходится использовать filter () для получения определенных элементов. Чем больше запросов DOM вам придется выполнить в прослушивателе событий прокрутки, который часто запускает прокрутку, тем менее отзывчивым он будет.

4. Когда я обновляю свой код, чтобы включить for-loop, вместо повторения блоков кода с изменением только одного числа, это больше не работает. Итак, чтобы уточнить, я пытаюсь уменьшить количество строк кода с помощью for-loop, но, похоже, это работает не так, как я думал (совсем не работает).

5. Спасибо, @PeterB! Это сделало свое дело. Я заблудился в своих кавычках.

Ответ №1:

$("#jhscroller-menu li a").removeClass("active"); — Вы всегда удаляете класс на каждой итерации, фактически отменяя все, что вы делали на предыдущих итерациях.

Вы можете избежать фиксированного количества итераций, выполнив (обратите внимание, что я добавляю класс CSS, потому что это имеет больше семантического смысла, чем сканирование для href): <a class="content-link" href="#anything" />

 var $contentLinks=$('a.content-link');
for(var i=0; i<$contentLinks.length; i  ){  // More efficient than .each()
    var $link=$($contentLinks[i]);
        $section=$($link.attr('href'));
    if($section.offset().top>windowpos){
        $link.addClass('active');
    }
}
  

Обратите внимание, что обычно нет необходимости добавлять .active как к привязке, так и к содержащимся в ней точкам, вы можете переписать css для точек, используя вложенный селектор ( .active .jhscroller-menu-prog-dot {...} ). Также по этой причине обычным соглашением является фактическая установка всех классов на <li> , чтобы CSS / HTML был более масштабируемым; просто добавьте его один раз в самый верхний элемент, представляющий элемент. Таким образом, кто-то, кто придет после вас, сможет изменить стиль всего на <li> и внутри него, просто используя CSS.