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

Vue3实现带子菜单导航栏遇异常,求错误排查与修复方案

问题:Vue3动态导航栏点击任意菜单项都显示子菜单

错误原因

你在循环生成菜单项时,所有下拉按钮的id和data-dropdown-toggle属性值都是固定的dropdownNavbarLink和dropdownNavbar,所有下拉菜单的id也都是dropdownNavbar。重复的id会导致点击任意按钮时,浏览器匹配所有同名id的元素,从而触发所有子菜单显示。

修复方法

给每个按钮和对应的下拉菜单生成唯一的id,利用循环中的item.id拼接标识即可:

修改后的完整代码

<template>
  <div class="container mx-auto max-w-screen-xl">
    <!--Navbar-->
    <div
      class="menu-line align-baseline justify-around hidden w-full mb-2 md:block"
    >
      <ul
        class="font-BPGBannerCaps text-sm flex flex-col justify-end tracking-wide bg-gray-50 border border-gray-100 md:flex-row md:space-x-8 md:mt-0 md:mb-0 md:text-base md:font-medium md:border-0 md:bg-white"
      >
        <li v-for="item in menu" :key="item.id">
          <!-- 生成唯一的按钮id和toggle目标 -->
          <button
            :id="`dropdownNavbarLink-${item.id}`"
            :data-dropdown-toggle="`dropdownNavbar-${item.id}`"
            class="flex justify-between items-center w-full font-medium text-gray-700 rounded hover:bg-gray-100 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 md:w-auto"
          >
            {{ item.name }}
            <svg
              v-if="item.submenu.length"
              class="ml-1 w-5 h-5"
              aria-hidden="true"
              fill="currentColor"
              viewBox="0 0 20 20"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                fill-rule="evenodd"
                d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
                clip-rule="evenodd"
              ></path>
            </svg>
          </button>
          <!-- Dropdown menu - 对应唯一的id -->
          <div
            :id="`dropdownNavbar-${item.id}`"
            class="hidden z-10 w-56 font-normal bg-white rounded divide-y divide-gray-100 shadow"
          >
            <ul
              class="py-1 text-sm text-gray-700 dark:text-gray-400"
              aria-labelledby="dropdownLargeButton"
              v-if="item.submenu.length"
            >
              <!-- 子项key改用索引,避免重复 -->
              <li v-for="(subitem, index) in item.submenu" :key="index">
                <a href="#" class="block py-2 px-4 hover:bg-gray-100">{{
                  subitem
                }}</a>
              </li>
            </ul>
          </div>
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const menu = ref([
  {
    id: 1,
    name: "Programs",
    submenu: ["Sub-1", "Sub-2", "Sub-3", "Sub-4"],
  },
  { id: 2, name: "Events", submenu: [] },
  { id: 3, name: "Publications", submenu: [] },
  { id: 4, name: "Tutorials", submenu: ["Tut-1", "Tut-2"] },
  { id: 5, name: "About Us", submenu: [] },
]);
</script>

额外优化提示

子项循环的key不要复用父项的item.id,改用子项的索引或者子项本身(如果子项是唯一字符串),避免同一个父项的子项key重复,符合Vue的key绑定规范。

内容的提问来源于stack exchange,提问作者ussrback

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:01:34