Vue3 + RouteLinks+headless UI:点击后菜单不关闭

问题描述 投票:0回答:1

我有一个带有 vue-router 和无头 UI 的 Vue3 项目。 在我的导航栏组件中,我想要一个下拉菜单。对于 dropDownMenu,我遇到了无头 UI 菜单组件 https://headlessui.com/vue/menu

在 headlessUI 示例中,他们使用

<a>
标签作为链接,这确实按预期工作。单击后菜单确实关闭。如果我使用
<RouterLink>...</RouterLink>
我将被重定向到相关路径和视图,但菜单不会关闭。

我尝试使用 close() 插槽道具,如下所示 https://headlessui.com/vue/menu#ending-menus-manually但它仍然不起作用。

  1. 为什么不与
    <RouterLink>
    合作?
  2. 我应该使用
    <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>

路线链接菜单

vuejs3 vue-router headless-ui
1个回答
0
投票

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); 
},
© www.soinside.com 2019 - 2024. All rights reserved.