我有一个带有 vue-router 和无头 UI 的 Vue3 项目。 在我的导航栏组件中,我想要一个下拉菜单。对于 dropDownMenu,我遇到了无头 UI 菜单组件 https://headlessui.com/vue/menu。
在 headlessUI 示例中,他们使用
<a>
标签作为链接,这确实按预期工作。单击后菜单确实关闭。如果我使用 <RouterLink>...</RouterLink>
我将被重定向到相关路径和视图,但菜单不会关闭。
我尝试使用 close() 插槽道具,如下所示 https://headlessui.com/vue/menu#ending-menus-manually但它仍然不起作用。
<RouterLink>
合作?<a>
代替 RouterLink
吗? (据我所知,<a>
应该用于外部导航,就像其他页面(youtube等)一样,vue-router用于内部页面下面是我的代码: 导航栏:
<template >
<header class="sticky top-0 shadow-lg bg-navbar" v-show="loggedIn">
<nav class="container flex flex-col sm:flex-row items-center gap-4 ">
<div class="px-2 pt-2 sm:flex">
<RouterLink :to="{name:'profile'}">
<p class=" mt-1 block px-2 py-1 font-semibold rounded hover:bg-navbar-buttons " >Meine Medien</p>
</RouterLink>
<RouterLink v-if="showLoanBoard" :to="{name:'ausleihe'}">
<p class="mt-1 block px-2 py-1 font-semibold rounded hover:bg-navbar-buttons">Ausleihe/Rückname</p>
</RouterLink>
<InvetoryDropDown v-if="showInventoryDropDown" />
<InventoryMenu v-if="showInventoryDropDown"/>
<InventoryMenuCopy v-if="showInventoryDropDown"/>
<AdminDropDownVue v-if="showAdminDropDown" />
</div>
<div>
<button
class=""
@click="logout">Logout</button>
</div>
</nav>
</header>
</template>
<script setup>
import AdminDropDownVue from './AdminDropDown.vue';
import InvetoryDropDown from './InventoryDropDown.vue';
import InventoryMenu from './InventoryMenu.vue';
import InventoryMenuCopy from './InventoryMenuCopy.vue';
import { computed, ref } from 'vue';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue'
const store = useStore();
const router = useRouter();
const loggedIn = computed(() =>{
return store.state.auth.status.loggedIn;
})
//A computed ref! Access with .value
const currentUser = computed(() =>{
return store.state.auth.user;
})
const showAdminDropDown = computed(() =>{
if(currentUser.value && currentUser.value.roles){
return currentUser.value['roles'].includes('ADMIN')
}
})
const showLoanBoard = computed(() =>{
if(currentUser && currentUser.value.roles){
return currentUser.value['roles'].includes('LIBRARIAN')
||currentUser.value['roles'].includes('ADMIN')
||currentUser.value['roles'].includes('LOAN_HELPER')
}
})
const showInventoryDropDown = computed(() =>{
if(currentUser && currentUser.value.roles){
return currentUser.value['roles'].includes('LIBRARIAN')
|| currentUser.value['roles'].includes('ADMIN')
|| currentUser.value['roles'].includes('INVENTORY_HELPER')
}
})
const logout = () => {
store.dispatch('auth/logout');
router.push('/login')
}
</script>
带有
<a>
的菜单
<template>
<Menu as="div" class="relative inline-block text-left">
<div>
<MenuButton class="inline-flex w-full justify-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
A href
<ChevronDownIcon class="-mr-1 h-5 w-5 text-gray-400" aria-hidden="true" />
</MenuButton>
</div>
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
<MenuItems class="absolute right-0 z-10 mt-2 w-56 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<div class="py-1">
<MenuItem v-slot="{ active }">
<a href="/inventory" :class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']">Übersicht</a>
</MenuItem>
<MenuItem v-slot="{ active }">
<a href="/inventory/add" :class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']">Aufnehmen</a>
</MenuItem>
<MenuItem v-slot="{ active }">
<a href="/inventory/delete" :class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']">Löschen</a>
</MenuItem>
</div>
</MenuItems>
</transition>
</Menu>
</template>
<script setup>
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { ChevronDownIcon } from '@heroicons/vue/20/solid'
</script>
带有
RouterLink
的菜单,单击时不会关闭
<template>
<Menu as="div" class="relative inline-block text-left">
<div>
<MenuButton class="inline-flex w-full justify-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
RouteLinks
<ChevronDownIcon class="-mr-1 h-5 w-5 text-gray-400" aria-hidden="true" />
</MenuButton>
</div>
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
<MenuItems class="absolute right-0 z-10 mt-2 w-56 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<div class="py-1">
<MenuItem v-slot="{ close }">
<RouterLink
:class="[close ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']" to="/inventory"
@click="close">
Übersicht
</RouterLink>
</MenuItem>
<MenuItem v-slot="{ close }">
<RouterLink @click="close" :class="[close ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block px-4 py-2 text-sm']" to="/inventory/add">Aufnehmen</RouterLink>
</MenuItem>
</div>
</MenuItems>
</transition>
</Menu>
</template>
<script setup>
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { ChevronDownIcon } from '@heroicons/vue/20/solid'
</script>
RouterLink 中的 @click 侦听器不起作用。我不确定这是一个很好的解决方案,但我是这样解决的:
<MenuItem v-for="item in userNavigation" :key="item.name" v-slot="{ active, close }">
<a @click="close, routerLinkMethod(item.href)">
{{ item.name }}
</a>
</MenuItem>
方法中:
routerLinkMethod(href) {
this.$router.push(href);
},