#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.