点击Produtos元素时事件触发但导航列表类切换失效问题
导航列表关闭功能修复方案
问题描述
网站中点击指定元素会弹出导航列表,要求满足三个关闭条件:点击页面body区域、滚动页面、再次点击“Produtos”元素。目前前两个功能正常,但点击“Produtos”时,alert能正常触发,却无法切换列表的visivel和invisivel类,列表仅能通过滚动或点击body关闭。
原始代码
HTML
<div class="cabecalho-lista"> <ul class="cabecalho__lista"> <li class="cabecalho__item"> <a class="cabecalho__item__link" href="index.html">Home</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">Linha Ignite</a> </li> <li class="lista-produtos__item"> <a href="produtos.html#elfbar">Linha Elfbar</a> </li> <li class="lista-produtos__item"> <a href="produtos.html#oxbar">Linha Oxbar</a> </li> <li class="lista-produtos__item"> <a href="produtos.html#lost">Linha Lost Mary</a> </li> </ul> </li> </div> <li class="cabecalho__item"> <a class="cabecalho__item__link" href="contato.html">FAQ</a> </li> </ul> </div>
CSS
.visivel { display: block; } .invisivel { display: none; }
JavaScript
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"); // Para fechar a lista: 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("ola"); listaProdutos.classList.add("invisivel"); listaProdutos.classList.remove("visivel"); }); } else { listaProdutos.classList.add("invisivel"); listaProdutos.classList.remove("visivel"); } } });
问题根源
- 重复事件绑定:每次checkbox的
change事件触发(选中状态),都会给produtos元素和body重复绑定点击/滚动事件,导致事件叠加,后续触发时逻辑冲突。 - 事件冒泡:点击
Produtos的a标签时,事件会冒泡到body,触发body的点击事件——先执行produtos的隐藏逻辑,接着body的事件又执行一次,同时checkbox被设置为true,造成状态混乱。 - 默认跳转干扰:
Produtos是a标签,点击会触发页面跳转,JS逻辑执行后页面立即刷新,导致看不到列表隐藏的效果(仅alert能弹出)。
修复代码
修改后的JavaScript
let listaProdutos = document.querySelector(".lista-produtos"); let checkBoxProdutos = document.querySelector("#menu"); let produtos = document.getElementById("link-produtos"); let body = document.querySelector("body"); // 初始化媒体查询对象 const mobileQuery = window.matchMedia("(max-width: 849px)"); // 统一的列表隐藏函数,避免重复代码 function hideProdutosList() { listaProdutos.classList.add("invisivel"); listaProdutos.classList.remove("visivel"); checkBoxProdutos.checked = false; } // 点击body区域隐藏列表(排除Produtos自身区域) body.addEventListener("click", function(e) { if (!e.target.closest(".cabecalho__item__produtos")) { hideProdutosList(); } }); // 滚动页面时隐藏列表 body.addEventListener("mousewheel", hideProdutosList); // 点击Produtos切换列表显示/隐藏 produtos.addEventListener("click", function(e) { // 阻止移动端下的默认跳转行为 if (mobileQuery.matches) { e.preventDefault(); // 阻止事件冒泡到body,避免触发body的隐藏逻辑 e.stopPropagation(); if (listaProdutos.classList.contains("visivel")) { hideProdutosList(); } else { listaProdutos.classList.add("visivel"); listaProdutos.classList.remove("invisivel"); checkBoxProdutos.checked = true; } } // 非移动端保持正常跳转 }); // checkbox状态变更处理 checkBoxProdutos.addEventListener("change", function () { if (mobileQuery.matches) { this.checked ? (listaProdutos.classList.add("visivel"), listaProdutos.classList.remove("invisivel")) : hideProdutosList(); } });
关键修改点
- 将事件绑定移到checkbox的
change事件外部,避免重复绑定事件导致的逻辑冲突。 - 添加
hideProdutosList统一函数,集中处理列表隐藏和checkbox状态重置,减少冗余代码。 - body的点击事件中增加判断,点击目标属于Produtos区域时不执行隐藏逻辑,避免事件冒泡干扰。
- 在Produtos的点击事件中,移动端下阻止默认跳转和事件冒泡,根据当前列表状态切换显示/隐藏;非移动端保持正常跳转,不影响桌面端体验。
- 优化checkbox的逻辑判断,使用三元运算符简化代码。
内容的提问来源于stack exchange,提问作者user26579796
相关产品推荐
相关产品推荐

