iamlorddop
@iamlorddop

Как сделать чтобы при нажатии на кнопку открывался только один элемент, а не все?

Этот код срабатывает так, что при нажатии на кнопку показываются все скрытые блоки, а нужно чтобы проявлялся только один из них при нажатии на кнопку

let spoiler = document.querySelectorAll('.spoilers-item');
let spoilerBig = document.querySelectorAll('.spoilers-item__big');
let spoilerBtn = document.querySelectorAll('.isshow');
spoilerBtn.forEach(e => {
  e.addEventListener( "click" , () => {
    spoilerBig.forEach(element => {
      element.classList.toggle('is-show');
    });
  });
})
  • Вопрос задан
  • 233 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Сразу определим селекторы элементов и класс, они нам дальше понадобятся:

const blockSelector = 'селектор блоков';
const buttonSelector = 'селектор кнопок';
const activeClass = 'класс, показывающий блок';

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

const blocks = document.querySelectorAll(blockSelector);
const buttons = document.querySelectorAll(buttonSelector);

buttons.forEach((n, i) => {
  n.addEventListener('click', () => {
    blocks[i].classList.toggle(activeClass);
  });
});

Кстати, создавать отдельные обработчики клика для каждой из кнопок не обязательно, можно сделать один общий. Как при этом получать индексы? - их можно прицепить прямо к кнопкам. Например, в виде data-атрибута:

const onClick = function({ currentTarget: { dataset: { index } } }) {
  this[index].classList.toggle(activeClass);
}.bind(document.querySelectorAll(blockSelector));

document.querySelectorAll(buttonSelector).forEach((n, i) => {
  n.dataset.index = i;
  n.addEventListener('click', onClick);
});

Также есть вариант вычислять индекс при клике:

const blocks = document.querySelectorAll(blockSelector);
const buttons = document.querySelectorAll(buttonSelector);

buttons.forEach(n => n.addEventListener('click', onClick));

function onClick() {
  const index = Array.prototype.indexOf.call(buttons, this);
  blocks[index].classList.toggle(activeClass);
}

А вообще, если у каждой из пар кнопка-блок есть отдельный общий предок (const containerSelector = '...';), то индексы не нужны. Достаточно от нажатой кнопки подняться до общего предка кнопки и блока, и найти внутри блок (а можно даже и не искать, если добавлять класс контейнеру; конечно, стили придётся в этом случае немного изменить, вместо .блок.класс будет .контейнер.класс .блок):

const toggleBlock = button => button
  ?.closest(containerSelector)
  ?.querySelector(blockSelector)
  .classList
  .toggle(activeClass);


// можно добавить обработчик клика каждой кнопке индивидуально
document.querySelectorAll(buttonSelector).forEach(function(n) {
  n.addEventListener('click', this);
}, e => toggleBlock(e.currentTarget));

// или один раз на всю страницу
document.addEventListener('click', e => {
  toggleBlock(e.target.closest(buttonSelector));
});
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы