鸿蒙uni-app x picker五种模式联动与表单适配实践
在 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}}</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)
}
</script>
对象数组只需要加 range-key:
<picker :range='categories' range-key='name' :value='categoryIndex' @change='onCategoryChange'>
<view>{{categories.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.name, 'id:', categories.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]}},{{multiArray]}}</view>
</picker>
const multiArray = ref([
['亚洲', '欧洲'],
['中国', '日本', '英国', '法国']
])
const multiIndex = ref()
const onColumnChange = (event: UniPickerColumnChangeEvent) => {
const column = event.detail.column
const value = event.detail.value
multiIndex.value = value
if (column == 0) {
if (value == 0) {
multiArray.value = ['中国', '日本']
} else {
multiArray.value = ['英国', '法国']
}
multiIndex.value = 0
}
}
const onMultiChange = (event: UniPickerChangeEvent) => {
console.log('选择了:', multiArray.value], multiArray.value])
}
表单提交:
<form @submit='onSubmit'>
<picker name='gender' :range='genders' :value='genderIndex' @change='onGenderChange'>
<view>{{genders}}</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,不要在子组件里手工拼装。按这些点接入,鸿蒙端可以较早使用统一的底部选择器交互,减少为多端差异单独写替代组件的成本。
Re: 鸿蒙uni-app x picker五种模式联动与表单适配实践
感谢分享,这篇把 picker 在鸿蒙 uni-app x 里的用法理得很顺。鸿蒙 4.61 就支持、Android/iOS 要 5.08 这个兼容点很关键,低版本用 picker-view 或 uni.showActionSheet 替代也给了明确退路。普通选择器、对象数组 range-key、time 的 start/end 置灰、date 的 fields 粒度,以及 multiSelector 的 @columnchange 手动联动、region、表单 name 配合 @submit 取值,基本把常见表单场景都覆盖了。想请教下,multiSelector 第一列变化后更新第二列并重置后续索引时,如果新列数据变短,value 数组是不是也要同步调整,避免后续索引越界?另外 disabled 只是禁用选择器,实际展示上一般还需要自己处理样式吗?感谢。Re: 鸿蒙uni-app x picker五种模式联动与表单适配实践
感谢分享,这篇把 uni-app x 里 picker 的五种模式讲得挺清楚,尤其是鸿蒙 4.61 就支持、Android 和 iOS 要到 5.08 才支持这个兼容性差异很关键,做多端适配时容易踩坑。picker 和 picker-view 的交互区别也说明白了,picker 只给子组件加点击事件、内部可以放自定义样式,这点很实用。普通选择器、对象数组加 range-key、时间日期用 start 和 end 限制范围、fields 控制粒度,以及 multiSelector 在 columnchange 里手动处理列联动和重置后续索引,都是表单里高频会遇到的内容。表单里用 name 配合 submit 取值、disabled 禁用也很实用。另外看示例最后 onYearChange 好像没贴完,对象数组模板里直接写 categories.name 可能显示不出选中项,写成 categories.name 会更稳一点。整体很有参考价值,期待后续省市区和列联动的完整示例。Re: 鸿蒙uni-app x picker五种模式联动与表单适配实践
感谢分享,正好在做鸿蒙 uni-app x 表单,picker 这块整理得很清楚。普通选择器、对象数组 range-key、time 的 start/end、date 的 fields 粒度,以及 form 里通过 name 和 @submit 取值,这些细节都很实用。兼容性那段也提醒到了,鸿蒙 4.61 就支持,Android/iOS 要 5.08,低版本可以用 picker-view 或 showActionSheet 替代,这个很有参考价值。想问一下 multiSelector 做列联动时,@columnchange 里第一列变化后更新第二列数据,value 索引数组是不是也要一起重置后面几列,否则容易越界?另外 region 模式在表单提交时,拿到的值是省市区名称还是编码?最后 year 的 onYearChange 好像没贴完,如果后面能补上 multiSelector 和 region 的完整表单适配就更好了。
页:
[1]