uni-app 中无原生 uni-select,推荐优先使用官方 uni-data-select(需处理分类占位和数据格式),其次选 uView 的 u-select;自定义方案须解决 iOS 键盘遮挡、滚动穿透等问题。

uni-app 里没有 uni-select,得自己封装或用现成的兼容方案
uni-app 官方组件库不提供下拉筛选框(即带搜索、多选/单选、可滚动列表的 select 替代品),picker 组件只支持纯列表弹层,不支持输入过滤;input + view 列表模拟又容易在 iOS 上触发软键盘遮挡、滚动穿透、z-index 失效等问题。
实际开发中建议分场景处理:
- 若只需「单选 + 分类展示」:用
picker+picker-view,配合range和range-key渲染分类数据,最轻量且全端兼容 - 若需「输入筛选 + 高亮 + 键盘收起控制」:必须自定义下拉面板,核心是用
position: fixed+z-index+@click.stop阻断事件冒泡,iOS 上还要监听focus/blur手动收键盘 - 若项目已引入
uView或uni-ui:直接用u-select(uView)或uni-data-select(uni-ui),但注意后者依赖uni-datetime-picker的基础样式,H5 端正常,小程序端需确认基础库版本 ≥ 2.10.3
用 uni-data-select 实现带搜索的分类选择器(推荐快速上线)
uni-data-select 是 uni-app 官方推出的可搜索下拉组件,支持远程加载、本地数据、分类字段(category-field)、禁用项(disabled-field),但默认不显示分类标题——需要手动 patch 数据结构。
常见问题和实操要点:
- 搜索失效?检查是否传了
localdata(数组)而非data(Object),且每项必须有value和text字段;text字段值会被用于模糊匹配 - 分类不显示?
uni-data-select不原生支持分组标题,需把原始分类数据拍平,并插入占位对象:{ value: '', text: '热门品牌', disabled: true },再设disabled-field="disabled" - H5 端点击空白收起正常,小程序端需加
popup属性并绑定v-model:show="showSelect",否则 touchmove 会穿透 - 性能注意:数据量 > 200 条时,建议开启
lazy-load并配合loadMore事件做分页拉取
示例关键片段:
<uni-data-select v-model="selected" :localdata="filteredList" placeholder="请选择分类" :popup="true" :disabled-field="'disabled'"></uni-data-select>
其中 filteredList 是处理后的数组,含真实选项和带 disabled: true 的分类标识项。
自定义下拉筛选框时,iOS 键盘遮挡和滚动穿透怎么破
这是自定义方案最常翻车的点:点击 input 拉起键盘后,下拉列表被顶出可视区;滚动列表时页面也跟着动;点击列表项后键盘不自动收起。
关键修复手段:
- 列表容器必须用
position: fixed+top/bottom显式定位,不能依赖 relative + absolute,否则 iOS 微信内嵌 WebView 会错算位置 - 给列表外层加
@touchmove.stop,防止滚动穿透;同时在input的focus回调里调用uni.pageScrollTo({scrollTop: 0})强制置顶(避免键盘推高后列表被切掉) - 选中后必须手动执行
uni.hideKeyboard(),且要在$nextTick后调用,否则部分安卓机型无效 - 不要用
v-show控制下拉显隐——它不释放 DOM,会导致多次渲染后内存泄漏;改用v-if+ 唯一 key
分类选择器的「多级联动」别硬套 picker-view
很多开发者试图用 picker-view 做省市区三级联动,结果发现滑动不同列时数据异步加载卡顿、无法精确控制每列高度、Android 上惯性滑动停不准。
更稳的做法是分层展开:
- 第一级用
uni-data-select或按钮式分类入口(如「手机」「电脑」「配件」) - 第二级开始用「页面跳转」或「折叠面板」(
uni-collapse),避免在单个弹层里堆三层picker-view-column - 如果坚持用弹层内联动,优先选用
u-cascader(uView),它内部用scroll-view+bindscroll实现懒加载列,比原生picker-view更可控 - 注意:所有联动数据必须提前扁平化,不要在滑动时实时请求接口,否则用户滑到一半就卡住
真正难的不是怎么画出来,而是让 iOS 微信、安卓 QQ、H5 Chrome 在各种基础库版本下都表现一致——这点上,官方组件的兼容性兜底能力远超手写代码,能用 uni-data-select 就别自己造轮子。











