You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击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");
    }
  }
});

问题根源

  1. 重复事件绑定:每次checkbox的change事件触发(选中状态),都会给produtos元素和body重复绑定点击/滚动事件,导致事件叠加,后续触发时逻辑冲突。
  2. 事件冒泡:点击Produtos的a标签时,事件会冒泡到body,触发body的点击事件——先执行produtos的隐藏逻辑,接着body的事件又执行一次,同时checkbox被设置为true,造成状态混乱。
  3. 默认跳转干扰: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:35:55