在 uni-app x 里开发鸿蒙表单时,picker 是常用组件,用于选城市、时间、日期、分类等。它从底部弹出滚动选择器,通过 mode 切换普通选择器、多列选择器、时间选择器、日期选择器、省市区选择器五种模式。兼容性上,鸿蒙从 4.61 开始支持,Android/iOS 要到 5.08 才支持,鸿蒙端反而更早可用;如果 Android/iOS 低于 5.08,可用 picker-view 或 uni.showActionSheet 替代。
picker 与 picker-view 的差异在交互形态:picker-view 内嵌页面,picker 点击后从底部弹出,类似 iOS ActionSheet。picker 本身不显示 UI,只给子组件添加点击事件,所以可以在内部放自定义样式的子组件。它可理解为基于 picker-view 封装出的弹出形态。
selector 普通模式:range 绑定数组,value 绑定索引,@change 从 event.detail.value 取选中索引;对象数组用 range-key 指定显示字段。time 模式 value 为时:分,start/end 限制可选范围,范围外置灰不可选。date 模式用 fields 控制粒度,day 为年-月-日,month 为年-月,year 为年。multiSelector 模式 range 为二维数组,value 为索引数组,列联动在 @columnchange 中手动处理,第一列变化时更新第二列数据并重置后续索引。region 用于省市区选择。表单中给 picker 设置 name,配合 form 的 @submit 从 event.detail.value 取数据;disabled 可禁用选择器。
普通选择器示例:- <template>
- <picker :range='cities' :value='cityIndex' @change='onCityChange'>
- <view>{{cities[cityIndex]}}</view>
- </picker>
- </template>
- <script setup lang='uts'>
- const cities = ['北京', '上海', '广州', '深圳', '杭州', '成都']
- const cityIndex = ref(0)
- const onCityChange = (event: UniPickerChangeEvent) => {
- cityIndex.value = event.detail.value as number
- console.log('选择了:', cities[cityIndex.value])
- }
- </script>
复制代码
对象数组只需要加 range-key:- <picker :range='categories' range-key='name' :value='categoryIndex' @change='onCategoryChange'>
- <view>{{categories[categoryIndex].name}}</view>
- </picker>
- type Category = {
- id: number
- name: string
- }
- const categories = [
- { id: 1, name: '美食' },
- { id: 2, name: '旅游' },
- { id: 3, name: '科技' },
- { id: 4, name: '教育' }
- ] as Array<Category>
- const categoryIndex = ref(0)
- const onCategoryChange = (event: UniPickerChangeEvent) => {
- categoryIndex.value = event.detail.value as number
- console.log('选择了:', categories[categoryIndex.value].name, 'id:', categories[categoryIndex.value].id)
- }
复制代码
时间和日期:- <picker mode='time' :value='time' start='09:00' end='21:00' @change='onTimeChange'>
- <view>{{time}}</view>
- </picker>
- <picker mode='date' :value='date' start='2020-01-01' end='2030-12-31' @change='onDateChange'>
- <view>{{date}}</view>
- </picker>
- <picker mode='date' fields='month' :value='month' @change='onMonthChange'>
- <view>{{month}}</view>
- </picker>
- <picker mode='date' fields='year' :value='year' @change='onYearChange'>
- <view>{{year}}</view>
- </picker>
- const time = ref('12:00')
- const date = ref('2025-06-25')
- const month = ref('2025-06')
- const year = ref('2025')
- const onTimeChange = (event: UniPickerChangeEvent) => {
- time.value = event.detail.value as string
- }
- const onDateChange = (event: UniPickerChangeEvent) => {
- date.value = event.detail.value as string
- }
- const onMonthChange = (event: UniPickerChangeEvent) => {
- month.value = event.detail.value as string
- }
- const onYearChange = (event: UniPickerChangeEvent) => {
- year.value = event.detail.value as string
- }
复制代码
多列选择器联动:- <picker mode='multiSelector' :range='multiArray' :value='multiIndex' @columnchange='onColumnChange' @change='onMultiChange'>
- <view>{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}}</view>
- </picker>
- const multiArray = ref([
- ['亚洲', '欧洲'],
- ['中国', '日本', '英国', '法国']
- ])
- const multiIndex = ref([0, 0])
- const onColumnChange = (event: UniPickerColumnChangeEvent) => {
- const column = event.detail.column
- const value = event.detail.value
- multiIndex.value[column] = value
- if (column == 0) {
- if (value == 0) {
- multiArray.value[1] = ['中国', '日本']
- } else {
- multiArray.value[1] = ['英国', '法国']
- }
- multiIndex.value[1] = 0
- }
- }
- const onMultiChange = (event: UniPickerChangeEvent) => {
- console.log('选择了:', multiArray.value[0][multiIndex.value[0]], multiArray.value[1][multiIndex.value[1]])
- }
复制代码
表单提交:- <form @submit='onSubmit'>
- <picker name='gender' :range='genders' :value='genderIndex' @change='onGenderChange'>
- <view>{{genders[genderIndex]}}</view>
- </picker>
- <picker name='birthday' mode='date' :value='birthday' @change='onBirthdayChange'>
- <view>{{birthday}}</view>
- </picker>
- <button form-type='submit' type='primary'>提交</button>
- </form>
- const genders = ['男', '女', '保密']
- const genderIndex = ref(0)
- const birthday = ref('2000-01-01')
- const onGenderChange = (event: UniPickerChangeEvent) => {
- genderIndex.value = event.detail.value as number
- }
- const onBirthdayChange = (event: UniPickerChangeEvent) => {
- birthday.value = event.detail.value as string
- }
- const onSubmit = (event: UniFormSubmitEvent) => {
- console.log('表单数据:', event.detail.value)
- }
复制代码
适配与排障要点:先确认鸿蒙版本不低于 4.61;覆盖 Android/iOS 且低于 5.08 时准备 picker-view 或 uni.showActionSheet 降级。对象数组要设置 range-key,否则显示字段不对。多列联动必须在 @columnchange 同时维护 range 和 value,只改 range 容易列错位。时间用 start/end 限定,日期用 fields 控制粒度。表单取值依赖 name 与 form 的 @submit,不要在子组件里手工拼装。按这些点接入,鸿蒙端可以较早使用统一的底部选择器交互,减少为多端差异单独写替代组件的成本。 |