Поскольку я не уверен, правильно ли я понял ваш вопрос, я быстро перефразирую его своими словами.
Вопрос: «У меня есть произвольное количество элементов списка, каждый из которых содержит кнопку и вложенный список. Кнопка всегда отображается, вложенный список по умолчанию скрыт. Когда пользователь нажимает на кнопку, соответствующий должен быть показан вложенный список. В то же время все остальные показанные вложенные списки должны быть снова скрыты. Как мне этого добиться? "
Оригинальный HTML выглядит нормально:
<div class="main">
<ul>
<li><a href="#" class="button">One</a>
<ul>
<li><a href="#">One-1</a></li>
<li><a href="#">One-2</a></li>
</ul>
</li>
<li><a href="#" class="button">Two</a>
<ul>
<li><a href="#">Two-1</a></li>
<li><a href="#">Two-2</a></li>
</ul>
</li>
<li><a href="#" class="button">Three</a>
<ul>
<li><a href="#">Three-1</a></li>
<li><a href="#">Three-2</a></li>
</ul>
</li>
</ul>
</div>
CSS я не до конца понял, но предлагаю следующее:
.main ul ul {
display: none;
}
.main li.is-active ul {
display: block;
}
.main ul ul li {
display: block;
}
При добавлении класса is-active к элементу LI он отображается. Таким образом, CSS контролирует видимость.
Для части JavaScript я предлагаю следующее:
const buttonElements = Array.from(document.querySelectorAll('.button'));
buttonElements.forEach(buttonElement => {
buttonElement.addEventListener('click', () => {
const activeElements = Array.from(document.querySelectorAll('.is-active'));
activeElements.forEach(activeElement => {
activeElement.classList.remove('is-active');
});
buttonElement.parentElement.classList.add('is-active');
});
});
В этом решении предполагается, что вы можете использовать более новые версии JavaScript / ECMAScript. В целом, он использует функции const и arrow.
Во-первых, мы получаем все элементы с классом «кнопка» с помощью document.querySelectorAll () . Поскольку в результате получается NodeList без массива, мы конвертируем его с помощью Array.from () . После этого мы перебираем массив с помощью Array.prototpye.forEach () . Мы добавляем прослушиватель событий для события «click». Когда кнопка нажата, мы ищем все элементы с классом is-active и для каждого удаляем ее. Наконец, мы добавляем класс is-active к родительскому элементу нажатой кнопки, используя Node.prototype.parentElement () .
Вот еще одно решение, которое работает в старых браузерах:
var buttonElements = document.getElementsByClassName('button');
for (var i = 0; i < buttonElements.length; i++) {
buttonElements[i].addEventListener('click', function(event) {
var activeListElements = document.getElementsByClassName('is-active');
for (var i = 0; i < activeListElements.length; i++) {
activeListElements[i].setAttribute('class', '');
}
event.target.parentNode.setAttribute('class', 'is-active');
});
}
Это почти то же самое, что и другой подход, но работает со старыми версиями JavaScript.
Как правило, идея состоит в том, чтобы сосредоточиться на произвольной сумме элементов вместо массива с определенной длиной. На естественном языке что-то вроде: «Дайте мне все кнопки. Для каждой кнопки добавьте прослушиватель событий. Когда нажата кнопка, дайте мне все активные элементы списка и удалите их активный статус. Затем отметьте элемент списка над кнопкой как активный ».
Надеюсь, это поможет