带有浮动 Vue 和 Tailwind 的 Vue 下拉菜单
可用于在 Vue 应用程序中创建工具提示、弹出框和菜单的最流行的库之一是floating-vue。虽然floating-vue提供了一个Dropdown组件,但它的样式和添加其他功能(例如键盘导航)由用户决定。 我们将创建什么 我们将使用floating-vue的Dropdown组件作为基础,然后在顶部添加键盘功能。然后,我们将使用该组件使用 Tailwind 创建一个下拉菜单。 最终结果将类似于
可用于在 Vue 应用程序中创建工具提示、弹出框和菜单的最流行的库之一是floating-vue。虽然floating-vue
提供了一个Dropdown组件,但它的样式和添加其他功能(例如键盘导航)由用户决定。
我们将创建什么
我们将使用floating-vue
的Dropdown
组件作为基础,然后在顶部添加键盘功能。然后,我们将使用该组件使用 Tailwind 创建一个下拉菜单。
最终结果将类似于Bootstrap 的下拉组件。
让我们开始吧!
下拉组件
幸运的是,Vue.js 允许我们使用“包装组件”技术轻松扩展任何组件。所以我们的最终组件将包括floating-vue
Dropdown 的所有功能以及:
-
能够使用光标上/下键在单个下拉项目中移动
-
用于键盘导航的下拉项目的可定制 CSS 选择器
-
当下拉触发器有焦点时,用
Space
和Enter
键打开和关闭下拉 -
使用键盘导航菜单时防止页面滚动
-
单击外部或使用
Esc
键关闭下拉菜单
zoz100037
<template>
<FloatingVueDropdown ref="popoverRef" :distance="14" :triggers="['click']" theme="dropdown-menu" placement="bottom-start" auto-hide @show="onShow" @hide="onHide">
<template v-for="(_, slot) in $slots" #[slot]="scope">
<slot :name="slot" v-bind="scope || {}" />
</template>
</FloatingVueDropdown>
</template>
<script setup>
import { Dropdown as FloatingVueDropdown } from 'floating-vue';
import { onBeforeUnmount, ref } from 'vue';
const popoverRef = ref(null);
const props = defineProps({
itemSelector: {
type: String,
default: 'li > a:not(:disabled)',
},
});
const popoverKeydown = (e) => {
const popover = popoverRef.value;
if (!popover) {
return;
}
if (['ArrowUp', 'ArrowDown'].includes(e.key)) {
e.preventDefault();
const items = [...popover.$refs.popperContent.$el.querySelectorAll(props.itemSelector)];
if (!items.length) {
return;
}
let index = items.indexOf(e.target);
index = e.key === 'ArrowDown' ? index + 1 : index - 1;
items[index]?.focus();
}
if ((e.key === 'Enter' || e.key === ' ') && e.target === popover.$refs.popperContent.$el) {
e.preventDefault();
popover.hide();
}
};
const onShow = () => {
document.addEventListener('keydown', popoverKeydown);
};
const onHide = () => {
document.removeEventListener('keydown', popoverKeydown);
const popover = popoverRef.value;
popover?.$refs.popper.$_targetNodes[0].focus();
};
onBeforeUnmount(() => {
document.removeEventListener('keydown', popoverKeydown);
});
</script>
<style>
.v-popper--theme-dropdown-menu .v-popper__arrow-container {
display: none;
}
</style>
进入全屏模式 退出全屏模式
最重要部件的分解
- 将槽传递给
floating-vue
下拉组件。
<FloatingVueDropdown>
<template v-for="(_, slot) in $slots" #[slot]="scope">
<slot :name="slot" v-bind="scope || {}" />
</template>
</FloatingVueDropdown>
进入全屏模式 退出全屏模式
- 设置一些组件默认值
*ref="popoverRef"
- 弹出框ref
,我们需要它来进行与 DOM 相关的操作。
*:distance="14"
- 设置下拉触发器和下拉菜单之间的距离
*:triggers="['click']"
- 点击打开下拉菜单
*theme="dropdown-menu"
- 将 a 主题设置为我们自己的主题,基本上删除所有默认的floating-vue``Dropdown
样式。
*placement="bottom-start"
- 下拉菜单的默认位置
*auto-hide @show="onShow"
- 显示Dropdown
时运行的方法
*@hide="onHide"
- 当Dropdown
被隐藏时运行的方法
-
itemSelector
属性 - 这是组件将在内部使用的选择器,以获取键盘导航将循环通过的下拉项目。 -
popoverKeydown
方法 - 此方法在显示下拉列表时注册为document``keydown
侦听器(在onShow
方法中),包括所有键盘功能。我们正在侦听向上/向下箭头按键,并根据方向在一个项目上设置focus
的下拉项目的Array
循环。我们还监听Enter
和Space
按键,所以当这些发生在下拉触发器上时,我们打开下拉菜单。注意e.preventDefault();
的用法,这是为了在打开下拉菜单时使用向上/向下键时页面不会滚动。 -
onHide
方法移除document``keydown
监听器并将焦点返回到下拉触发器。
结构和样式
我们已经准备好了基础Dropdown
组件,让我们用它来使用 Tailwind 创建一个下拉菜单!
App.vue
<template>
<Dropdown class="inline" popper-class="w-64 bg-white border rounded-lg shadow-md">
<!-- Dropdown trigger -->
<button
class="inline-block px-6 py-3 bg-blue-600 text-white leading-tight rounded hover:bg-blue-700 focus:bg-blue-700 focus:outline-none focus:ring-0 active:bg-blue-800 transition duration-150 ease-in-out"
>
Dropdown button
</button>
<!-- Dropdown content -->
<template #popper="{ hide }">
<ul class="py-1 text-gray-70">
<li>
<a href="#" class="block py-2 px-4 hover:bg-gray-100 focus:bg-gray-100 outline-none" @click="hide">
Click me to close
</a>
</li>
<li>
<a href="#" class="block py-2 px-4 hover:bg-gray-100 focus:bg-gray-100 outline-none">Menu item</a>
</li>
<li>
<a href="#" class="block py-2 px-4 hover:bg-gray-100 focus:bg-gray-100 outline-none">Another menu item</a>
</li>
</ul>
</template>
</Dropdown>
</template>
<script setup>
import Dropdown from './Dropdown.vue'
</script>
进入全屏模式 退出全屏模式
而已!
这是Stackblitz 的最终结果的实时示例,这里是。
您可能还想查看vue-simple-dropdown,这是一个floating-vue
的下拉组件,可以导入到您的 Vue 项目中!
更多推荐
所有评论(0)