Вопрос или проблема
На моем сайте, когда вы нажимаете на элемент, список навигации открывается прямо над ним. Этот список закрывается, когда пользователь кликает в другую часть страницы (body), прокручивает страницу (body) и когда снова нажимает на элемент с именем “Produtos”.
Я сделал часть с body, но последний элемент не работает!
let listaProdutos = document.querySelector(".lista-produtos");
let checkBoxProdutos = document.querySelector("#menu");
let produtos = document.getElementById("link-produtos");
checkBoxProdutos.addEventListener("change", function () {
x = window.matchMedia("(max-width: 849px)");
if (x.matches) {
if (this.checked) {
listaProdutos.classList.add("visivel");
listaProdutos.classList.remove("invisivel");
// Чтобы закрыть список:
let body = document.querySelector("body");
body.addEventListener("click", function () {
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
checkBoxProdutos.checked = true;
});
body.addEventListener("mousewheel", function () {
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
});
produtos.addEventListener("click", function () {
alert("привет");
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
});
} else {
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
}
}
});
.visivel {
display: block;
}
.invisivel {
display: none;
}
<div class="cabecalho-lista">
<ul class="cabecalho__lista">
<li class="cabecalho__item">
<a class="cabecalho__item__link" href="https://stackoverflow.com/questions/78999721/index.html">Главная</a>
</li>
<div class="cabecalho__item-produtos">
<li class="cabecalho__item cabecalho__item__produtos">
<input class="produtos-celular" type="checkbox" id="menu" />
<label for="menu">
<a
class="cabecalho__item__link"
id="link-produtos"
href="produtos.html"
>Produtos</a
>
</label>
<ul class="lista-produtos invisivel">
<li class="lista-produtos__item">
<a href="produtos.html#ignite">Линия Ignite</a>
</li>
<li class="lista-produtos__item">
<a href="produtos.html#elfbar">Линия Elfbar</a>
</li>
<li class="lista-produtos__item">
<a href="produtos.html#oxbar">Линия Oxbar</a>
</li>
<li class="lista-produtos__item">
<a href="produtos.html#lost">Линия Lost Mary</a>
</li>
</ul>
</li>
</div>
<li class="cabecalho__item">
<a class="cabecalho__item__link" href="contato.html">Часто задаваемые вопросы (FAQ)</a>
</li>
</ul>
</div>
Когда слушатель реагирует на клик по “produtos”, алерт срабатывает нормально, но класс, который очищает навигационный список, просто не работает!
Список исчезает только тогда, когда пользователь прокручивает или кликает по body.
Ответ или решение
Ваша проблема заключается в том, что у вас есть конфликт между обработчиками событий, а также порядок их выполнения. В приведенном вами коде вы используете обработчик события для клика по элементу "Produtos" (ссылка), который вызывает событие, мешая правильному закрытию списка продуктов.
Решение проблемы
Чтобы сделать так, чтобы список продуктов закрывался при повторном нажатии на элемент "Produtos", вам нужно предотвратить всплытие события клика, когда пользователь нажимает на элемент. Вам также нужно выполнить логику переключения видимости списка продуктов в этом обработчике клика.
Вот обновленный код, который должен исправить вашу проблему:
let listaProdutos = document.querySelector(".lista-produtos");
let checkBoxProdutos = document.querySelector("#menu");
let produtos = document.getElementById("link-produtos");
checkBoxProdutos.addEventListener("change", function () {
let x = window.matchMedia("(max-width: 849px)");
if (x.matches) {
if (this.checked) {
listaProdutos.classList.add("visivel");
listaProdutos.classList.remove("invisivel");
} else {
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
}
}
});
// Для закрытия списка при клике вне
document.body.addEventListener("click", function (e) {
if (!checkBoxProdutos.checked || !e.target.closest(".cabecalho__item-produtos")) {
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
checkBoxProdutos.checked = false; // Отменяем чекбокс
}
});
// Обработчик для клика на "Produtos"
produtos.addEventListener("click", function (e) {
e.preventDefault(); // Предотвращаем переход по ссылке
// Переключаем состояние списка продуктов
if (checkBoxProdutos.checked) {
listaProdutos.classList.add("invisivel");
listaProdutos.classList.remove("visivel");
checkBoxProdutos.checked = false; // Закрываем меню
} else {
listaProdutos.classList.add("visivel");
listaProdutos.classList.remove("invisivel");
checkBoxProdutos.checked = true; // Открываем меню
}
});
Объяснение изменений:
-
Предотвращение всплытия события: Убедитесь, что при клике на элемент "Produtos" код не переходит по ссылке, используя
e.preventDefault()
. Это предотвращает нежелательные переходы и позволяет вам обращаться к переключению состояния меню. -
Переключение состояния: Я добавил логику переключения в обработчик события клика на элементе "Produtos". Если чекбокс уже установлен, мы закрываем меню (убираем класс
visivel
и добавляем классinvisivel
), и наоборот. - Закрытие меню при клике вне: Мы добавляем дополнительный обработчик на
document.body
, который проверяет, был ли клик вне области меню. Если это так, то мы скрываем меню и сбрасываем состояние чекбокса.
Теперь все должно работать корректно — меню будет открываться и закрываться по клику, а также при клике куда-либо еще на странице.