vue 实现菜单下拉
使用 Vue 实现菜单下拉
基础实现(v-show/v-if + @click)
通过 v-show 或 v-if 控制下拉菜单的显示/隐藏,配合点击事件切换状态:
<template>
<div class="dropdown">
<button @click="toggleDropdown">菜单</button>
<ul v-show="isOpen" class="dropdown-menu">
<li><a href="#">选项1</a></li>
<li><a href="#">选项2</a></li>
<li><a href="#">选项3</a></li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
isOpen: false
}
},
methods: {
toggleDropdown() {
this.isOpen = !this.isOpen;
}
}
}
</script>
<style>
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-menu {
position: absolute;
background: white;
border: 1px solid #ddd;
list-style: none;
padding: 0;
margin: 0;
}
</style>
点击外部关闭(使用指令)
通过自定义指令实现点击外部区域关闭菜单:
// 全局指令
Vue.directive('click-outside', {
bind(el, binding, vnode) {
el.clickOutsideEvent = function(event) {
if (!(el === event.target || el.contains(event.target))) {
vnode.context[binding.expression](event);
}
};
document.body.addEventListener('click', el.clickOutsideEvent);
},
unbind(el) {
document.body.removeEventListener('click', el.clickOutsideEvent);
}
});
// 组件内使用
<template>
<div v-click-outside="closeDropdown">
<!-- 下拉菜单内容 -->
</div>
</template>
过渡动画(Vue Transition)
为下拉菜单添加平滑的显示/隐藏动画:
<transition name="fade">
<ul v-show="isOpen" class="dropdown-menu">
<!-- 菜单项 -->
</ul>
</transition>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s, transform 0.3s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
transform: translateY(-10px);
}
</style>
组件化封装
将下拉菜单封装为可复用组件:
<!-- Dropdown.vue -->
<template>
<div class="dropdown" v-click-outside="close">
<div @click="toggle">
<slot name="trigger"></slot>
</div>
<transition name="fade">
<div v-show="isOpen" class="dropdown-content">
<slot></slot>
</div>
</transition>
</div>
</template>
<!-- 父组件使用 -->
<dropdown>
<template v-slot:trigger>
<button>自定义触发器</button>
</template>
<a href="#">选项1</a>
<a href="#">选项2</a>
</dropdown>
键盘导航支持
增强可访问性,支持键盘操作:

methods: {
handleKeydown(e) {
if (!this.isOpen) return;
switch(e.key) {
case 'Escape':
this.close();
break;
case 'ArrowDown':
// 焦点移动到下一个菜单项
break;
case 'ArrowUp':
// 焦点移动到上一个菜单项
break;
}
}
}
注意事项
- 移动端设备可能需要添加
@touchstart事件支持 - 多层嵌套菜单需要考虑 z-index 层级问题
- 对于复杂场景,可以考虑使用现成的 UI 库如 Element UI 的
el-dropdown组件






