如何解决Vue.js中所有下拉菜单同时打开的问题?

1tu0hz3e  于 2022-11-17  发布在  Vue.js
关注(0)|答案(1)|浏览(157)

我已经创建了一个应用程序,用于获得待办事项列表形式的任务。这些列表可以编辑和删除。我想在列表中添加一个下拉菜单,帮助我们访问列表更新或删除页面。但问题是,每当我单击下拉图标时,所有列表的下拉菜单都会同时打开。有人能帮助我解决这个问题吗?我正在附上我的Vue。JS代码和我的 Jmeter 板截图,其中的列表存在。
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>

截图:
第一次

fnx2tebb

fnx2tebb1#

为了使每个列表独立运行,您应该隔离相关代码。最合乎逻辑的做法是隔离显示项目的代码部分。隔离的逻辑是,每个项目都有自己的showMenu变量,一次只允许对其中一个执行操作。
组件父级

<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">
            <Items :item="item"/> //Call Component Items
        </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" }],
    };
  },
  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);
    }
  },
  components: {
    Navbar, Items
  },
  created() {
    this.getTrackers();
  },
};
</script>

组件子项(物料)

<template>
<div>
  <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>
      </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>
</template>

<script>
export default {

  props: {
    item: Item,
  },

  data() {
    return {
      showMenu: false,
    };
  },
  
  methods: {
    toggleMenu() {
      this.showMenu = !this.showMenu;
    },
    itemClicked() {
      this.toggleMenu();
    },
  },
};
</script>

相关问题