@Reflections

Как выбрать все элементы кроме текущего в forEach?

Здравствуйте.

Подскажите пожалуйста, как выбрать все элементы кроме текущего внутри forEach?
Имеется меню, нужно, чтобы класс .active одновременно мог иметь только 1 пункт меню.
  • Вопрос задан
  • 300 просмотров
Решения вопроса 1
mizutsune
@mizutsune
Frontend Developer
Варианты решения с помощью делегирования событий:

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

const elements = document.querySelectorAll(".value-item");
const stateClasses = ["value-active", "basic__shadow"];

document.addEventListener("click", ({ target }) => {
   if (!target.classList.contains("value-item")) return;
   elements.forEach(v => v.classList.remove(...stateClasses));
   target.classList.add(...stateClasses);
});


Или:

Почти всё тоже самое что и в первом варианте - за исключением того в этот раз будем работать без цикла. Находим элемент с "активными" классами и удаляем их, после чего добавим эти классы текущему элементу, на котором и произошел клик:

const stateClasses = ["value-active", "basic__shadow"];

document.addEventListener("click", ({ target }) => {
   if (!target.classList.contains("value-item")) return;
   const activeItem = document.querySelector(".value-active");
   activeItem && activeItem.classList.remove(...stateClasses);
   target.classList.add(...stateClasses);
});


Варианты решения с помощью цикла forEach:

const elements = document.querySelectorAll(".value-item");
const stateClasses = ["value-active", "basic__shadow"];

const toggleActiveElement = element => {
   element.addEventListener("click", () => {
      elements.forEach(n => n.classList.remove(...stateClasses));
      element.classList.add(...stateClasses);
   });
};

elements.forEach(v => toggleActiveElement(v));


Или:

const elements = document.querySelectorAll(".value-item");
const stateClasses = ["value-active", "basic__shadow"];

const toggleActiveElement = element => {
   element.addEventListener("click", () => {
      document.querySelector(".value-active")?.classList.remove(...stateClasses);
      element.classList.add(...stateClasses);
   });
};

elements.forEach(v => toggleActiveElement(v));


Однако у этих двух вариантов есть небольшие минусы и для таких целей как переключение активного класса при клике, хорошо подходит делегирование событий. Но почему в большинстве случаев не стоит использовать цикл для решения подобных задач?

1. Вы заставляете браузер искать все элементы с определенным классом на странице.
2. Добавляется обработчик на каждый элемент, хотя возможно пользователь и не кликнет на этот элемент.
3. addEventListener добавленный через цикл к каждому элементу определенного NodeList - не будет работать на динамически добавленных элементах. Разумеется если не добавить к ним обработчики, после создания, но это конечно так себе работа.

Возможно есть и другие побочные эффекты и/или минусы у такого решения задачи.

Обычно добавление обработчиков в цикле используется в связи с недостатком опыта или просто потому что данный способ в той или иной степени решает поставленную задачу и делать по другому тупо нет желания или смысла. Но даже если отказ от подобных решений и является просто напросто экономией на спичках и/или чем-то там ещё, в любом случае лучше использовать инструменты и функции по назначению, а не потому что просто так хочется или "удобно".

Правда всё же есть исключения когда добавление обработчиков в цикле оправданно и будет наиболее подходящим способом решить задачу чем например через делегирование событий.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Kentavr16
@Kentavr16
long cold winter
Внутри forEach элементы невозможно "выбирать". Эта операция пробегается ПО ВСЕМ элементам. Если же ты хочешь проигнорировать какой-то элемент, можешь использовать условие if внутри forEach.
Ответ написан
SlavaMaxwell
@SlavaMaxwell
Frontend разработчик
До события клика ты сперва их удаляешь, в событии добавляешь через classList.add
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 05:01
999999 руб./за проект
19 апр. 2024, в 03:52
1000 руб./за проект
19 апр. 2024, в 03:01
1000 руб./за проект