Vue.js中解决所有下拉菜单同时展开问题的方法
问题描述
我开发了一款用于管理待办事项(todo)列表的应用,支持列表的编辑与删除操作。我希望为每个列表添加下拉菜单,以跳转到列表更新或删除页面,但遇到问题:点击下拉图标时,所有列表的下拉菜单会同时展开。附上我的Vue.js代码及仪表盘截图,恳请帮助解决该问题。
DashboardView.vue 代码
<template> <div class="dashboard"> <Navbar class="navbar__dash" /> <h1 class="dashboard__welcome">Welcome {{ name }}</h1> <div class="listview"> <div class="no__lists" v-if="len_list === 0"> <h2 class="no_lists">There are No lists here tap to add</h2> </div> <div class="has__lists" v-else> <div class="all__lists" v-for="(item, index) in items" :key="index"> <div class="list"> <div class="title"> <div class="title__options"> <h1 class="list_name">{{ item.list_name }}</h1> <div class="dropdown"> <button @click="toggleMenu"> <fa class="dropdown_icon" icon="fa-solid fa-arrow-down" /> </button> <div v-if="showMenu" class="menu"> <div class="menu-item" v-for="(item, index) in links_list" :key="index" @click="itemClicked" > {{ item.title }} </div> </div> </div> <!-- V-menu --> <!--menu ends--> </div> </div> <div class="body"> <div class="no_tasks" v-if="item.no_of_tasks === 0"> <h3>There are no tasks added yet</h3> </div> <div class="has_tasks" v-else> <h4>Here are your tasks</h4> </div> </div> <div class="footer"> Number of Completed tasks: {{ item.no_completed }}/{{ item.no_of_tasks }} </div> </div> </div> </div> <router-link :to="`/createList/${id}`"> <fa class="plus__icon" icon="fa-solid fa-plus" /> </router-link> </div> </div> </template> <script> import axios from 'axios'; import Navbar from '../components/NavBar.vue'; export default { name: 'DashboardView', data() { return { name: localStorage['name'], len_list: 0, items: [], id: localStorage['id'], links_list: [{ title: 'Click Me' }, { title: 'Click Me' }], showMenu: false, }; }, methods: { getTrackers() { const path = 'http://localhost:5000/dashboard/' + localStorage['id']; axios .get(path) .then((res) => { this.items = res.data.list; console.log(res.data.list); this.len_list = res.data.list[0]['len_list']; }) .catch((err) => { console.log(err); }); console.log(this.items); }, toggleMenu() { this.showMenu = !this.showMenu; }, itemClicked() { this.toggleMenu(); }, }, components: { Navbar, }, created() { this.getTrackers(); }, }; </script> <style> .dashboard { width: 100%; min-height: 100vh; color: #ffd700; background-image: url('../assets/wood-texture.jpg'); overflow-x: auto; overflow-y: hidden; } .dashboard__welcome { margin-top: 2rem; font-weight: 600; } .plus__icon { margin-left: 58rem; width: 32px; height: 32px; margin-top: 1rem; color: #ffd700; padding: 1rem; border: 1px solid #ffd700; border-radius: 50%; } .no_lists { text-align: center; margin-top: 15rem; } .navbar__dash { background-color: black; color: white; max-width: inherit; } .has__lists { display: flex; } .list { padding: 10rem; border: 1px solid #ffd700; border-radius: 2rem; width: 20%; margin-left: 1rem; margin-top: 5rem; padding-bottom: 0px; } .title { background: #ffd700; color: black; width: 320px; text-align: center; margin-left: -10rem; margin-top: -10rem; height: 100px; border-top-left-radius: 2rem; border-top-right-radius: 2rem; } .footer { margin-top: 10rem; background: #ffd700; color: black; width: 320px; margin-left: -10rem; margin-top: 0.01rem; margin-bottom: 0rem; height: 100px; border-bottom-left-radius: 2rem; border-bottom-right-radius: 2rem; text-align: center; } .body { background-color: white; width: 320px; color: grey; margin-left: -10rem; text-align: center; height: 10rem; } .list_name { margin-top: 0.6rem; padding: 2px; font-weight: 600; font-size: 20px; border-top-left-radius: 1rem; border-bottom-left-radius: 1rem; } .list__icon { width: 20px; height: 20px; } .title__options { display: flex; justify-content: center; } .dropdown_icon { padding: 0.2rem; color: #ffd700; background: black; margin-top: 15px; transition: var(--transition); border-radius: 2rem; } .dropdown_icon:hover { background: white; color: black; height: 20px; } .menu { background: white; padding-left: 2rem; padding-right: 2rem; border-radius: 1rem; } </style>
截图
- 仪表盘初始状态:

- 点击下拉按钮后的状态:

解决方案
问题根源是你用了一个全局的showMenu变量控制所有下拉菜单的显示/隐藏,点击时会同时切换所有菜单的状态。要解决这个问题,需要为每个列表项单独维护菜单状态,以下是两种常用方案:
方案1:给每个列表项添加独立的菜单状态
在获取列表数据时,为每个item添加showMenu字段,初始为false:
getTrackers() { const path = 'http://localhost:5000/dashboard/' + localStorage['id']; axios .get(path) .then((res) => { // 给每个列表项添加独立的showMenu属性 this.items = res.data.list.map(item => ({ ...item, showMenu: false })); this.len_list = res.data.list[0]['len_list']; }) .catch((err) => { console.log(err); }); }
修改模板和方法,针对当前item操作:
<!-- 点击事件传入当前列表项的索引 --> <button @click="toggleMenu(index)"> <fa class="dropdown_icon" icon="fa-solid fa-arrow-down" /> </button> <!-- 使用当前item的showMenu判断是否显示 --> <div v-if="item.showMenu" class="menu"> <div class="menu-item" v-for="(link, linkIndex) in links_list" :key="linkIndex" @click="itemClicked(index)" > {{ link.title }} </div> </div>
更新方法逻辑:
toggleMenu(index) { // 切换对应索引的列表项菜单状态 this.items[index].showMenu = !this.items[index].showMenu; }, itemClicked(index) { this.toggleMenu(index); // 这里可添加跳转逻辑,比如: // this.$router.push(`/editList/${this.items[index].id}`) }
方案2:维护当前展开菜单的索引
如果不想修改列表数据,可以在data中添加一个变量记录当前展开的菜单索引:
data() { return { // ...其他数据 activeMenuIndex: null }; }
修改模板和方法:
<!-- 点击事件传入当前列表项的索引 --> <button @click="toggleMenu(index)"> <fa class="dropdown_icon" icon="fa-solid fa-arrow-down" /> </button> <!-- 判断当前索引是否为激活状态 --> <div v-if="activeMenuIndex === index" class="menu"> <div class="menu-item" v-for="(link, linkIndex) in links_list" :key="linkIndex" @click="itemClicked()" > {{ link.title }} </div> </div>
更新方法逻辑:
toggleMenu(index) { // 点击当前展开的菜单则关闭,否则切换到该菜单 this.activeMenuIndex = this.activeMenuIndex === index ? null : index; }, itemClicked() { this.activeMenuIndex = null; // 这里添加跳转逻辑 }
额外优化建议
- 避免用
index作为v-for的key,尽量使用列表项的唯一ID(如item.id),提升Vue渲染效率。 - 可以给
links_list添加路径字段,比如{ title: '编辑列表', path: '/edit' },方便后续跳转逻辑的编写。
内容的提问来源于stack exchange,提问作者MAHEEDHAR A
相关产品推荐
相关产品推荐

