查看: 279|回复: 0

鸿蒙uni-app x picker五种模式联动与表单适配实践

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式
在 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 可禁用选择器。

普通选择器示例:
  1. <template>
  2.   <picker :range='cities' :value='cityIndex' @change='onCityChange'>
  3.     <view>{{cities[cityIndex]}}</view>
  4.   </picker>
  5. </template>
  6. <script setup lang='uts'>
  7. const cities = ['北京', '上海', '广州', '深圳', '杭州', '成都']
  8. const cityIndex = ref(0)
  9. const onCityChange = (event: UniPickerChangeEvent) => {
  10.   cityIndex.value = event.detail.value as number
  11.   console.log('选择了:', cities[cityIndex.value])
  12. }
  13. </script>
复制代码

对象数组只需要加 range-key:
  1. <picker :range='categories' range-key='name' :value='categoryIndex' @change='onCategoryChange'>
  2.   <view>{{categories[categoryIndex].name}}</view>
  3. </picker>
  4. type Category = {
  5.   id: number
  6.   name: string
  7. }
  8. const categories = [
  9.   { id: 1, name: '美食' },
  10.   { id: 2, name: '旅游' },
  11.   { id: 3, name: '科技' },
  12.   { id: 4, name: '教育' }
  13. ] as Array<Category>
  14. const categoryIndex = ref(0)
  15. const onCategoryChange = (event: UniPickerChangeEvent) => {
  16.   categoryIndex.value = event.detail.value as number
  17.   console.log('选择了:', categories[categoryIndex.value].name, 'id:', categories[categoryIndex.value].id)
  18. }
复制代码

时间和日期:
  1. <picker mode='time' :value='time' start='09:00' end='21:00' @change='onTimeChange'>
  2.   <view>{{time}}</view>
  3. </picker>
  4. <picker mode='date' :value='date' start='2020-01-01' end='2030-12-31' @change='onDateChange'>
  5.   <view>{{date}}</view>
  6. </picker>
  7. <picker mode='date' fields='month' :value='month' @change='onMonthChange'>
  8.   <view>{{month}}</view>
  9. </picker>
  10. <picker mode='date' fields='year' :value='year' @change='onYearChange'>
  11.   <view>{{year}}</view>
  12. </picker>
  13. const time = ref('12:00')
  14. const date = ref('2025-06-25')
  15. const month = ref('2025-06')
  16. const year = ref('2025')
  17. const onTimeChange = (event: UniPickerChangeEvent) => {
  18.   time.value = event.detail.value as string
  19. }
  20. const onDateChange = (event: UniPickerChangeEvent) => {
  21.   date.value = event.detail.value as string
  22. }
  23. const onMonthChange = (event: UniPickerChangeEvent) => {
  24.   month.value = event.detail.value as string
  25. }
  26. const onYearChange = (event: UniPickerChangeEvent) => {
  27.   year.value = event.detail.value as string
  28. }
复制代码

多列选择器联动:
  1. <picker mode='multiSelector' :range='multiArray' :value='multiIndex' @columnchange='onColumnChange' @change='onMultiChange'>
  2.   <view>{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}}</view>
  3. </picker>
  4. const multiArray = ref([
  5.   ['亚洲', '欧洲'],
  6.   ['中国', '日本', '英国', '法国']
  7. ])
  8. const multiIndex = ref([0, 0])
  9. const onColumnChange = (event: UniPickerColumnChangeEvent) => {
  10.   const column = event.detail.column
  11.   const value = event.detail.value
  12.   multiIndex.value[column] = value
  13.   if (column == 0) {
  14.     if (value == 0) {
  15.       multiArray.value[1] = ['中国', '日本']
  16.     } else {
  17.       multiArray.value[1] = ['英国', '法国']
  18.     }
  19.     multiIndex.value[1] = 0
  20.   }
  21. }
  22. const onMultiChange = (event: UniPickerChangeEvent) => {
  23.   console.log('选择了:', multiArray.value[0][multiIndex.value[0]], multiArray.value[1][multiIndex.value[1]])
  24. }
复制代码

表单提交:
  1. <form @submit='onSubmit'>
  2.   <picker name='gender' :range='genders' :value='genderIndex' @change='onGenderChange'>
  3.     <view>{{genders[genderIndex]}}</view>
  4.   </picker>
  5.   <picker name='birthday' mode='date' :value='birthday' @change='onBirthdayChange'>
  6.     <view>{{birthday}}</view>
  7.   </picker>
  8.   <button form-type='submit' type='primary'>提交</button>
  9. </form>
  10. const genders = ['男', '女', '保密']
  11. const genderIndex = ref(0)
  12. const birthday = ref('2000-01-01')
  13. const onGenderChange = (event: UniPickerChangeEvent) => {
  14.   genderIndex.value = event.detail.value as number
  15. }
  16. const onBirthdayChange = (event: UniPickerChangeEvent) => {
  17.   birthday.value = event.detail.value as string
  18. }
  19. const onSubmit = (event: UniFormSubmitEvent) => {
  20.   console.log('表单数据:', event.detail.value)
  21. }
复制代码

适配与排障要点:先确认鸿蒙版本不低于 4.61;覆盖 Android/iOS 且低于 5.08 时准备 picker-view 或 uni.showActionSheet 降级。对象数组要设置 range-key,否则显示字段不对。多列联动必须在 @columnchange 同时维护 range 和 value,只改 range 容易列错位。时间用 start/end 限定,日期用 fields 控制粒度。表单取值依赖 name 与 form 的 @submit,不要在子组件里手工拼装。按这些点接入,鸿蒙端可以较早使用统一的底部选择器交互,减少为多端差异单独写替代组件的成本。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-18 13:33 , Processed in 0.022996 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部