更新记录
1.0.0(2026-09-01)
下载此版本
- 输入框 + 下方可滚动选择列表,点击展开,点击遮罩/外部关闭
- 支持一键清除选中值(clearable)
- 支持上拉加载:滚动条触碰最底部且无数据加载时触发
loadMore 回调(配合 loading 防重复触发)
- 支持模糊搜索:输入关键词防抖后触发
search 回调接口,支持远程搜索(remote)与本地过滤(local)两种模式
- 支持
v-model 双向绑定、disabled 禁用、自定义字段映射(labelKey / valueKey)与空态/加载态文案
- 零依赖,兼容微信小程序、H5、App(vue)
平台兼容性
uni-app(4.87)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
- |
- |
√ |
- |
√ |
- |
- |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| √ |
√ |
√ |
√ |
√ |
√ |
- |
√ |
√ |
- |
- |
- |
其他
fg-select-dropdown 下拉列表选择器
组件名:fg-select-dropdown(uni_modules easycom 自动引入,也可手动引入)
版本:1.0.0
类似管理平台下拉列表选择的组件:一个输入框 + 输入框下方展示的可选择列表。点击输入框展开列表,点击外部区域收起。纯组件零依赖,兼容微信小程序、H5、App(vue)。
特性
- 输入框 + 下方可滚动选择列表:点击输入框展开,点击透明遮罩 / 外部区域关闭
- 一键清除选择:有选中值或有输入内容时显示清除按钮,点击一键清空
- 上拉加载:滚动条触碰列表最底部且当前无数据加载(
loading 为 false)时触发 loadMore 回调,配合父组件 loading 状态防止重复请求
- 模糊搜索触发回调接口:输入关键词防抖(默认 300ms)后触发
search 回调,由父组件调用搜索接口;也支持 local 模式按 label 本地模糊过滤
v-model 双向绑定、disabled 禁用、自定义字段映射(labelKey / valueKey)、空态 / 加载中 / 没有更多文案自定义
快速使用
uni_modules 插件默认开启 easycom,页面中直接使用即可,无需注册:
<fg-select-dropdown
v-model="value"
:list="list"
:loading="loading"
:has-more="hasMore"
placeholder="请输入关键词搜索"
@search="onSearch"
@load-more="onLoadMore"
/>
手动引入
import FgSelectDropdown from '@/uni_modules/fg-select-dropdown/components/fg-select-dropdown/fg-select-dropdown.vue'
export default {
components: { FgSelectDropdown }
}
属性说明
| 属性名 |
类型 |
默认值 |
说明 |
| modelValue |
String / Number / Object / Array |
'' |
选中值,支持 v-model,与列表项 valueKey 字段对应 |
| placeholder |
String |
'请选择' |
输入框占位符 |
| list |
Array |
[] |
下拉列表数据,每项需包含 labelKey / valueKey 对应字段 |
| labelKey |
String |
'label' |
列表项显示文案字段名 |
| valueKey |
String |
'value' |
列表项选中值字段名 |
| searchable |
Boolean |
true |
输入框是否可输入搜索;false 时输入框为只读展示,点击仅展开列表 |
| filterMode |
String |
'remote' |
remote 远程搜索(输入防抖触发 search 回调接口);local 本地按 label 模糊过滤 |
| searchDebounce |
Number |
300 |
搜索防抖毫秒数 |
| clearOnInput |
Boolean |
true |
输入时是否清空已选中值(远程搜索下旧选中值通常不再有效) |
| clearable |
Boolean |
true |
是否显示一键清除按钮 |
| disabled |
Boolean |
false |
是否禁用 |
| loading |
Boolean |
false |
是否正在加载数据(父组件控制;true 时不触发 loadMore 并展示加载文案) |
| hasMore |
Boolean |
true |
是否还有更多数据(false 且列表非空时展示「没有更多了」) |
| emptyText |
String |
'暂无数据' |
空数据文案 |
| loadingText |
String |
'加载中...' |
加载中文案 |
| noMoreText |
String |
'没有更多了' |
没有更多文案 |
| maxHeight |
String |
'400rpx' |
下拉列表最大高度(rpx / px),决定列表可滚动区域 |
| lowerThreshold |
Number |
50 |
触底距离阈值(px),滚动条触碰底部附近即触发 loadMore |
| confirmType |
String |
'search' |
输入框键盘确认键类型(小程序) |
| placeholderStyle |
String |
'' |
占位符样式 |
事件说明
| 事件名 |
参数 |
说明 |
| update:modelValue |
value |
v-model 更新(选中 / 清除时) |
| change |
(value, item) |
选中值变化(value 为选中值,item 为完整列表项) |
| select |
item |
选中某个列表项 |
| clear |
- |
点击一键清除按钮 |
| search |
keyword |
模糊搜索回调(防抖后触发;清除时也会触发一次空关键词,用于重新加载完整列表) |
| loadMore |
- |
上拉加载回调:滚动条触碰最底部且 loading 为 false 时触发 |
| open |
- |
下拉列表展开 |
| close |
- |
下拉列表关闭 |
完整示例:远程搜索 + 分页 + 上拉加载 + 一键清除
<template>
<view class="page">
<fg-select-dropdown
v-model="userValue"
:list="userList"
:loading="loading"
:has-more="hasMore"
placeholder="请输入姓名搜索"
@open="onOpen"
@search="onSearch"
@load-more="onLoadMore"
@clear="onSearch('')"
@change="onChange"
/>
</view>
</template>
<script setup>
import { ref } from 'vue'
const userValue = ref('')
const userList = ref([])
const loading = ref(false)
const hasMore = ref(true)
const page = ref(1)
const keyword = ref('')
// 模拟分页搜索接口
function fetchList(kw, reset) {
loading.value = true
setTimeout(() => {
const all = ['张三', '李四', '王五', '赵六', '钱七', '孙八', '周九', '吴十', '郑十一', '冯十二']
.map((name, i) => ({ label: name, value: i + 1 }))
const kwLower = (kw || '').toLowerCase()
const filtered = all.filter((it) => it.label.toLowerCase().indexOf(kwLower) > -1)
const size = 5
const start = (reset ? 1 : page.value) - 1
const data = filtered.slice(start * size, start * size + size)
userList.value = reset ? data : userList.value.concat(data)
hasMore.value = userList.value.length < filtered.length
page.value = reset ? 2 : page.value + 1
loading.value = false
}, 400)
}
// 首次展开时加载第一页(list 为空时)
function onOpen() {
if (userList.value.length === 0) fetchList('', true)
}
// 模糊搜索:输入防抖后触发,拉取第一页
function onSearch(kw) {
keyword.value = kw
page.value = 1
fetchList(kw, true)
}
// 上拉加载:触底且未在加载时触发,追加下一页
function onLoadMore() {
fetchList(keyword.value, false)
}
function onChange(val, item) {
console.log('选中:', val, item)
}
</script>
本地过滤模式
数据量小、无需接口时,直接传入完整列表并开启 local:
<fg-select-dropdown
v-model="value"
filter-mode="local"
:list="options"
placeholder="输入关键词过滤"
/>
const options = [
{ label: '北京', value: 1 },
{ label: '上海', value: 2 },
{ label: '广州', value: 3 }
]
注意事项
- 下拉列表使用
scroll-view 滚动,内容高度超过 maxHeight 时才会出现滚动条并触发 loadMore;数据不足一屏时不会触发触底回调,属于正常行为
loadMore 的防重复触发依赖父组件同步 loading:接口请求期间务必把 loading 置为 true,返回后置 false
- 展开时组件会渲染一层全屏透明遮罩用于点击外部关闭,页面其他区域被遮罩拦截(点击即关闭),属弹层式下拉的正常交互
- 远程搜索下点击清除按钮会先清空值,再触发一次
search(''),以便父组件重新加载完整列表
label 与 value 字段可通过 labelKey / valueKey 映射为任意字段名(如 name / id)