使用 UniApp 实现带搜索功能的下拉菜单
前言
在移动应用开发中,下拉菜单是常见的交互控件,广泛应用于筛选、选择、导航等场景。带搜索功能的下拉菜单,能极大提升用户在选项较多时的查找效率。随着鸿蒙(HarmonyOS)生态的壮大,开发者对多端适配和高性能交互提出了更高要求。本文将以 UniApp 为例,详细讲解如何开发一个带搜索功能的下拉菜单组件,并结合鸿蒙平台的适配与优化建议。
一、需求与设计思路
1. 需求分析
- 支持输入关键词实时筛选下拉选项
- 支持选项高亮、点击选中
- 支持自定义选项内容与样式
- 兼容鸿蒙平台,适配不同分辨率
- 组件化设计,便于复用和扩展
2. 设计思路
- 使用 input 组件实现搜索输入
- 通过 v-for 渲染下拉选项,支持动态过滤
- 选项支持高亮关键词
- 选中后关闭下拉并回传选中值
- 结合 CSS 动画提升交互体验
二、核心代码实现
1. 组件结构
<template>
<view class="dropdown">
<view class="dropdown-input" @click="toggleMenu">
<input
v-model="search"
:placeholder="placeholder"
@input="onInput"
@focus="openMenu"
class="input"
:disabled="disabled"
/>
<text class="icon">▼</text>
</view>
<view v-if="showMenu" class="dropdown-menu">
<view v-if="filteredOptions.length === 0" class="empty">无匹配项</view>
<view
v-for="item in filteredOptions"
:key="item.value"
:class="['dropdown-item', { selected: item.value === value }]"
@click="select(item)"
>
<text v-html="highlight(item.label)"></text>
</view>
</view>
</view>
</template>
2. 脚本逻辑
<script>
export default {
name: 'SearchDropdown',
props: {
options: { type: Array, required: true },
value: { type: [String, Number], default: '' },
placeholder: { type: String, default: '请选择' },
disabled: { type: Boolean, default: false },
},
data() {
return {
showMenu: false,
search: '',
};
},
computed: {
filteredOptions() {
if (!this.search) return this.options;
return this.options.filter(opt =>
opt.label.toLowerCase().includes(this.search.toLowerCase())
);
},
},
methods: {
toggleMenu() {
if (this.disabled) return;
this.showMenu = !this.showMenu;
},
openMenu() {
if (this.disabled) return;
this.showMenu = true;
},
onInput(e) {
this.search = e.detail.value;
},
select(item) {
this.$emit('input', item.value);
this.$emit('change', item);
this.showMenu = false;
this.search = '';
},
highlight(label) {
if (!this.search) return label;
const reg = new RegExp(`(${this.search})`, 'ig');
return label.replace(reg, '<span class="hl">$1</span>');
},
},
};
</script>
3. 样式设计
<style scoped>
.dropdown {
position: relative;
width: 100%;
margin-bottom: 24rpx;
}
.dropdown-input {
display: flex;
align-items: center;
background: #fff;
border-radius: 12rpx;
border: 1rpx solid #eee;
padding: 0 24rpx;
height: 80rpx;
font-size: 28rpx;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
}
.input {
flex: 1;
border: none;
background: transparent;
font-size: 28rpx;
outline: none;
}
.icon {
margin-left: 12rpx;
color: #bbb;
font-size: 28rpx;
}
.dropdown-menu {
position: absolute;
left: 0; right: 0; top: 90rpx;
background: #fff;
border-radius: 12rpx;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.08);
z-index: 100;
max-height: 400rpx;
overflow-y: auto;
animation: fadeIn 0.2s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10rpx); }
to { opacity: 1; transform: translateY(0); }
}
.dropdown-item {
padding: 22rpx 28rpx;
font-size: 28rpx;
color: #333;
cursor: pointer;
transition: background 0.2s;
}
.dropdown-item.selected {
background: #e6f7ff;
color: #007aff;
}
.dropdown-item:active {
background: #f0faff;
}
.hl {
color: #ff4d4f;
font-weight: bold;
}
.empty {
text-align: center;
color: #bbb;
padding: 32rpx 0;
font-size: 26rpx;
}
</style>
三、父页面集成与使用示例
<template>
<search-dropdown
:options="cityList"
v-model="selectedCity"
placeholder="请选择城市"
/>
<view class="result">当前选择:{{ selectedCity }}</view>
</template>
<script>
import SearchDropdown from '@/components/SearchDropdown.vue';
export default {
components: { SearchDropdown },
data() {
return {
cityList: [
{ value: 'bj', label: '北京' },
{ value: 'sh', label: '上海' },
{ value: 'gz', label: '广州' },
{ value: 'sz', label: '深圳' },
{ value: 'cd', label: '成都' },
{ value: 'wh', label: '武汉' },
{ value: 'hz', label: '杭州' },
],
selectedCity: '',
};
},
};
</script>
<style scoped>
.result {
margin-top: 32rpx;
font-size: 28rpx;
color: #007aff;
}
</style>
四、鸿蒙平台适配与优化建议
- 分辨率适配:全程使用
rpx
单位,保证鸿蒙不同设备下的显示一致。 - 性能优化:下拉菜单建议本地渲染,避免频繁请求,提升鸿蒙设备流畅度。
- 动画与交互:鸿蒙设备对交互反馈要求高,建议下拉弹出/关闭使用 CSS3 动画。
- 安全区域适配:如有底部导航,注意
env(safe-area-inset-bottom)
。 - 无障碍适配:为输入框、选项等添加 aria-label,提升鸿蒙无障碍体验。
五、实际应用案例
- 城市选择器:支持快速搜索和选择城市,提升表单填写效率。
- 商品筛选:商品分类、品牌等下拉筛选,支持模糊搜索。
- 联系人选择:通讯录下拉搜索,支持高亮匹配。
六、总结与展望
带搜索功能的下拉菜单是提升移动端表单与筛选体验的利器。通过 UniApp 的组件化和跨平台特性,我们可以高效实现兼容鸿蒙的高性能下拉菜单。未来还可结合远程搜索、分组展示等进一步丰富场景。希望本文的讲解和代码示例能为你的项目带来启发,欢迎留言交流更多鸿蒙适配经验!