vue实现下拉框组件
Vue 下拉框组件实现
基础实现
创建基础下拉框组件,使用v-model实现双向数据绑定:
<template>
<div class="dropdown">
<div class="dropdown-toggle" @click="toggleDropdown">
{{ selectedOption || placeholder }}
</div>
<ul class="dropdown-menu" v-show="isOpen">
<li
v-for="option in options"
:key="option.value"
@click="selectOption(option)"
>
{{ option.label }}
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
options: {
type: Array,
required: true
},
placeholder: {
type: String,
default: '请选择'
},
value: {
type: [String, Number],
default: ''
}
},
data() {
return {
isOpen: false,
selectedOption: this.value
}
},
methods: {
toggleDropdown() {
this.isOpen = !this.isOpen
},
selectOption(option) {
this.selectedOption = option.label
this.$emit('input', option.value)
this.isOpen = false
}
}
}
</script>
<style scoped>
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-toggle {
padding: 8px 16px;
border: 1px solid #ccc;
cursor: pointer;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
width: 100%;
max-height: 200px;
overflow-y: auto;
}
.dropdown-menu li {
padding: 8px 16px;
cursor: pointer;
}
.dropdown-menu li:hover {
background-color: #f5f5f5;
}
</style>
高级功能扩展
添加搜索过滤功能:

<template>
<div class="dropdown">
<div class="dropdown-toggle" @click="toggleDropdown">
{{ selectedOption || placeholder }}
</div>
<ul class="dropdown-menu" v-show="isOpen">
<input
v-if="searchable"
v-model="searchQuery"
@click.stop
placeholder="搜索..."
class="search-input"
/>
<li
v-for="option in filteredOptions"
:key="option.value"
@click="selectOption(option)"
>
{{ option.label }}
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
searchable: {
type: Boolean,
default: false
}
},
data() {
return {
searchQuery: ''
}
},
computed: {
filteredOptions() {
if (!this.searchable) return this.options
return this.options.filter(option =>
option.label.toLowerCase().includes(this.searchQuery.toLowerCase())
)
}
}
}
</script>
自定义插槽支持
支持自定义选项模板:
<template>
<div class="dropdown">
<div class="dropdown-toggle" @click="toggleDropdown">
<slot name="toggle" :selected="selectedOption">
{{ selectedOption || placeholder }}
</slot>
</div>
<ul class="dropdown-menu" v-show="isOpen">
<slot
name="option"
v-for="option in filteredOptions"
:option="option"
:select="() => selectOption(option)"
>
<li @click="selectOption(option)">
{{ option.label }}
</li>
</slot>
</ul>
</div>
</template>
外部点击关闭
添加点击外部关闭下拉框功能:

mounted() {
document.addEventListener('click', this.handleClickOutside)
},
beforeDestroy() {
document.removeEventListener('click', this.handleClickOutside)
},
methods: {
handleClickOutside(event) {
if (!this.$el.contains(event.target)) {
this.isOpen = false
}
}
}
表单集成
与Vue表单验证集成:
<template>
<div class="dropdown-wrapper">
<div
class="dropdown"
:class="{ 'is-invalid': error }"
>
<!-- 下拉框内容 -->
</div>
<div v-if="error" class="error-message">
{{ error }}
</div>
</div>
</template>
<script>
export default {
props: {
rules: {
type: Array,
default: () => []
}
},
data() {
return {
error: ''
}
},
methods: {
validate() {
const errors = this.rules.map(rule => rule(this.selectedOption))
.filter(error => error)
this.error = errors[0] || ''
return !this.error
}
}
}
</script>
无障碍支持
添加ARIA属性提升无障碍体验:
<div
class="dropdown-toggle"
@click="toggleDropdown"
:aria-expanded="isOpen"
aria-haspopup="listbox"
role="button"
tabindex="0"
>
{{ selectedOption || placeholder }}
</div>
<ul
class="dropdown-menu"
v-show="isOpen"
role="listbox"
:aria-activedescendant="activeDescendant"
>
<!-- 选项列表 -->
</ul>
这些实现方法可以根据实际需求组合使用,构建功能完善的下拉框组件。






