在鸿蒙平台的 uni-app x 开发中,picker-view 与 picker 虽然只差一个单词,但定位完全不同。picker 是从底部弹出的选择器,点击后才出现;picker-view 是直接嵌入页面的滚动选择器,适合时间选择页、日期选择页、自定义地址选择等需要常驻展示的场景。需要常驻表单里选值用 picker,自定义选择页面用 picker-view。在鸿蒙平台,uni-app x 从 4.61 开始支持 picker-view,与 picker 同期。
兼容性与选型
picker-view 比 picker 支持更早:Android 3.9、iOS 4.11 已支持,而 picker 到 5.08 才支持。因此如果 Android/iOS 项目版本低于 5.08,可以用 picker-view 替代 picker。这是跨端兼容选型时值得注意的一点。
组件结构与关键数据
picker-view 是容器,picker-view-column 表示每一列,列内放置选项列表。value 是下标数组,不是实际值。change 事件通过 event.detail.value 返回当前各列下标。indicator-style 控制选中框样式,mask-style 控制蒙层样式,pickstart 和 pickend 用来监听滚动开始和结束。下面以日期选择为例,2025 年在 years 数组中下标是 25,所以初始 value 可以写成 [25,5,24]。
- const dateValue = ref([25, 5, 24]) // 2025年6月25日
- const onDateChange = (event: UniPickerViewChangeEvent) => {
- const val = event.detail.value
- year.value = years[val[0]]
- month.value = months[val[1]]
- day.value = days[val[2]]
- dateValue.value = val
- }
复制代码
时间选择需要三列时分秒,通常对个位数补零显示。自定义样式场景可通过 indicator-style 设置选中框高度、背景色和圆角,通过 mask-style 设置渐变蒙层,picker-view 自身可设置高度、背景和圆角。滚动监听场景则用 @pickstart 与 @pickend 更新“滚动中/停止”状态,适合在滚动结束后再做校验或联动。
动态列联动与索引越界
动态更新数据是 picker-view 最容易出问题的场景。以省市选择为例,省份变更后必须立即更新城市列表,并检查城市索引是否越界。如果新城市列表长度小于当前索引,要把 value 的对应列重置为 0,否则会出现选中项为空或显示错位。原文给出的处理逻辑是:change 中先更新省份,再替换 cities,若 val[1] >= cities.length 则把 value 设为 [val[0], 0],最后根据 value[1] 取城市;pickend 里再兜底更新一次城市。
- const onChange = (event: UniPickerViewChangeEvent) => {
- const val = event.detail.value
- value.value = val
- province.value = provinces[val[0]]
- cities.value = cityMap[province.value] || []
- if (val[1] >= cities.value.length) {
- value.value = [val[0], 0]
- }
- city.value = cities.value[value.value[1]]
- }
复制代码
适配与排障建议
第一,picker-view 的 value 始终按列下标维护,不要传实际文本;第二,列数据动态变化时要同步修正 value,尤其是联动选择;第三,选项 view 高度要与 indicator-style 高度一致,通常统一为 50px,避免选中框与文本错位;第四,Android/iOS 低版本可优先用 picker-view 规避 picker 5.08 的版本限制;第五,鸿蒙平台从 4.61 起支持,接入前确认 uni-app x 版本。picker-view 不是弹层组件,而是页面内嵌组件,适合把日期、时间、地区等选择器直接铺在表单或详情页中。 |