Skip to content

Picker 选择器

8:14

组件概况

Picker 选择器组件用于在预设的选项列表中进行单选或多选操作。该组件由 wd-picker(弹窗选择器)和 wd-picker-view(内联选择器视图)两个关联组件组成。wd-picker 以弹窗形式呈现,适用于表单填写场景;wd-picker-view 直接嵌入页面中,适用于需要常驻显示的选择器场景。两者共享相同的数据格式和列操作能力,支持单列选择、多列选择和多级联动选择,广泛应用于省市区选择、分类筛选、表单选项等场景。

核心功能描述

  • 弹窗选择模式wd-picker 内置底部弹出层,点击表单单元格后弹出选择面板,支持取消和确认操作
  • 内联嵌入模式wd-picker-view 直接嵌入页面布局中,实时响应选择变化,无需弹窗交互
  • 单列选择:支持一维数组数据源,适用于简单的单选场景
  • 多列选择:支持二维数组数据源,每一列独立滚动选择,适用于多字段组合选择
  • 多级联动:通过 column-change 回调函数,在列切换时动态更新后续列的数据源,实现省市区三级联动等场景
  • 自定义展示文案:通过 display-format 函数自定义单元格中显示的选中值文案格式
  • 确认前校验:通过 before-confirm 函数在点击确认按钮时执行异步校验,校验不通过可阻止确认
  • 禁用选项:选项对象支持 disabled 属性,被禁用的选项无法选中,自动选择距离最近的可用选项
  • 立即变更模式:通过 immediate-change 属性控制是否在手指松开时立即触发 change 事件
  • 加载状态:支持 loading 属性显示加载动画,wd-picker 还提供 setLoading() 方法供外部控制
  • 可清空:通过 clearable 属性显示清除按钮,一键清空已选值
  • 表单集成:支持表单校验功能,通过 proprules 属性与 wd-form 组件配合使用
  • 丰富的方法暴露wd-picker-view 暴露了获取选中项、设置列数据、重置列数据等完整的方法集

适用业务场景

  • 省市区选择:通过多级联动功能实现省/市/区三级联动选择
  • 分类筛选:在商品列表、内容列表页面提供分类、品牌等多维度筛选条件
  • 表单选项:在注册表单、信息填写页面提供下拉式选项选择,如学历、行业、职位等
  • 多字段组合选择:如学校+专业、品牌+型号等多字段组合场景
  • 时间/日期自定义选择:当内置的日期选择器不满足需求时,可自定义日期选项列表
  • 嵌入式选择器wd-picker-view 适用于需要在页面中常驻显示选择器的场景,如设置页面、筛选面板

API

wd-picker Props

属性名称类型默认值是否必填说明
modelValuestring / number / Array<string / number>''选中项的值。单列选择时为字符串或数字,多列选择时为数组
columnsArray<string / number / ColumnItem / Array<string / number / ColumnItem>>[]选择器数据源,可以为字符串数组、对象数组(ColumnItem),二维数组表示多列选择器
labelstring''选择器左侧文案(表单项标签)
placeholderstring请选择选择器未选中时的占位符文案
disabledbooleanfalse是否禁用选择器,禁用后无法点击打开弹窗
readonlybooleanfalse是否只读,只读状态下不可点击但样式与禁用不同
loadingbooleanfalse是否显示加载状态
loadingColorstring'#4D80F0'加载指示器的颜色
titlestring''弹出层标题,设置后在弹窗顶部中间显示
cancelButtonTextstring取消取消按钮文案,未设置时跟随国际化配置
confirmButtonTextstring完成确认按钮文案,未设置时跟随国际化配置
requiredbooleanfalse是否显示必填标记(星号)
sizestring''组件尺寸,可选值:large
labelWidthstring'33%'左侧标题宽度
errorbooleanfalse是否显示为错误状态,错误状态下选中内容显示为红色
alignRightbooleanfalse选中值是否靠右对齐显示
ellipsisbooleanfalse文本溢出时是否显示省略号
clearablebooleanfalse是否显示清除按钮
markerSidestring'before'必填标记位置,可选值:before(左侧)、after(右侧)
columnsHeightnumber217选项滚动区域的总高度,单位为 px
valueKeystring'value'选项对象中表示值的字段名
labelKeystring'label'选项对象中表示显示文本的字段名
immediateChangebooleanfalse是否在手指松开时立即触发 change 事件,仅在微信小程序和支付宝小程序中生效
displayFormatFunction默认格式化函数自定义展示文案的格式化函数,签名为 (items: ColumnItem | ColumnItem[], vl: { valueKey: string; labelKey: string }) => string,返回一个字符串
beforeConfirmFunction确认前校验函数,签名为 (value: string | number | boolean | string[] | number[] | boolean[], resolve: (isPass: boolean) => void, picker: PickerInstance) => void
columnChangeFunction列切换回调函数,签名为 (pickerView: PickerViewInstance, selects: Record\<string, any\> | Record\<string, any\>[], index: number, resolve: () => void) => void,用于多级联动场景
closeOnClickModalbooleantrue点击遮罩层是否关闭弹窗
safeAreaInsetBottombooleantrue是否在底部安全区域内显示(适配 iPhone X 等全面屏机型)
zIndexnumber15弹出层的层级
rootPortalbooleanfalse是否从页面中脱离出来,用于解决各种 fixed 定位失效问题
propstring''表单域 model 字段名,使用表单校验时必填
rulesArray<FormItemRule>[]表单验证规则,结合 wd-form 组件使用
customLabelClassstring''自定义 label 区域的样式类名
customValueClassstring''自定义 value 显示区域的样式类名
customViewClassstring''自定义内部 pickerView 视图区域的样式类名
customStylestring''自定义根节点样式
customClassstring''自定义根节点样式类

wd-picker-view Props

属性名称类型默认值是否必填说明
modelValuestring / number / boolean / Array<number> / Array<string> / Array<boolean>''选中项的值,类型需要与 columns 中的 value 类型保持一致
columnsArray<string / number / ColumnItem / Array<number> / Array<string> / Array<ColumnItem>>[]选择器数据源,格式与 wd-picker 一致
loadingbooleanfalse是否显示加载状态
loadingColorstring'#4D80F0'加载指示器的颜色
columnsHeightnumber217选项滚动区域的总高度,单位为 px
itemHeightnumber35每个选项项的高度,单位为 px
valueKeystring'value'选项对象中表示值的字段名
labelKeystring'label'选项对象中表示显示文本的字段名
immediateChangebooleanfalse是否在手指松开时立即触发 change 事件,仅在微信小程序和支付宝小程序中生效
columnChangeFunction列切换回调函数,签名与 wd-picker 相同,用于多级联动场景
customStylestring''自定义根节点样式
customClassstring''自定义根节点样式类

ColumnItem 数据结构

字段名类型默认值说明
valuestring / number / boolean-选项的值
labelstring-选项的显示文本
disabledbooleanfalse是否禁用该选项

wd-picker Events

事件名称触发条件参数类型回调数据说明
confirm点击确认按钮并完成校验后触发(data: { value: string | number | Array\<string | number\>; selectedItems: ColumnItem | ColumnItem[] })value 为选中项的值数组,selectedItems 为选中项的完整数据对象
cancel点击取消按钮或点击遮罩关闭弹窗时触发-
open弹窗打开时触发-
clear点击清除按钮清空选中值时触发-
update:modelValue绑定值更新时触发(v-model 内部使用)(value: string | number | Array\<string | number\>)值为确认后的新选中值

wd-picker-view Events

事件名称触发条件参数类型回调数据说明
change选择器滚动选中项变化时触发(data: { picker: PickerViewInstance; value: string | number | Array\<string | number\>; index: number })picker 为 pickerView 实例,value 为当前选中值,index 为变化列的下标(单列时为行下标)
pickstart手指开始触摸滚动时触发-
pickend手指结束触摸滚动时触发-
update:modelValue绑定值更新时触发(v-model 内部使用)(value: string | number | Array\<string | number\>)值为变化后的新选中值

wd-picker Methods

通过 ref 可以获取 wd-picker 实例并调用以下方法:

方法名称参数返回值说明
openvoid打开选择器弹出层
closevoid关闭选择器弹出层
setLoading(loading: boolean)void设置加载状态,true 为加载中,false 为加载完成

wd-picker-view Methods

通过 ref 可以获取 wd-picker-view 实例并调用以下方法:

方法名称参数返回值说明
getSelectsRecord\<string, any\> | Record\<string, any\>[]获取所有列的选中项数据对象,单列时返回单个对象,多列时返回对象数组
getValuesstring | number | Array\<string | number\>获取所有列的选中值,单列时返回单个值,多列时返回数组
getLabelsstring[]获取所有列选中项的 label 文本数组
getSelectedIndexnumber[]获取所有列选中项的索引数组
getColumnIndex(columnIndex: number)number获取指定列的选中项索引
getColumnData(columnIndex: number)Record\<string, string\>[]获取指定列的选项数据
getColumnsDataRecord\<string, string\>[][]获取所有列的选项数据
setColumnData(columnIndex: number, data: Array\<string | number | ColumnItem\>, rowIndex?: number)void设置指定列的数据源,rowIndex 为设置后的默认选中行下标,默认为 0
resetColumns(columns: Array\<string | number | ColumnItem | string[] | number[] | ColumnItem[]\>)void重置所有列的数据为指定数据

wd-picker Slots

插槽名称作用域参数使用场景
default-自定义触发选择器的元素,替换默认的 wd-cell 单元格
label-自定义左侧标签区域内容

wd-picker-view Slots

wd-picker-view 不提供自定义插槽。

使用示例

示例一:单列选择器

最基础的选择器用法,传入一维数组作为数据源,支持字符串数组和对象数组两种格式。

vue
<template>
  <wd-picker
    label="单列选项"
    v-model="value"
    :columns="columns"
    @confirm="handleConfirm"
  />
</template>

<script lang="ts" setup>
import { ref } from 'vue'

const value = ref('')

const columns = ref([
  { label: '选项一', value: '1' },
  { label: '选项二', value: '2' },
  { label: '选项三', value: '3' },
  { label: '选项四', value: '4' },
  { label: '选项五', value: '5' }
])

function handleConfirm({ value, selectedItems }: any) {
  console.log('选中值:', value)
  console.log('选中项:', selectedItems)
}
</script>

简洁写法,直接传入字符串数组(此时 value 和 label 均为字符串本身):

vue
<template>
  <wd-picker label="单列选项" v-model="value" :columns="columns" />
</template>

<script lang="ts" setup>
import { ref } from 'vue'

const value = ref('')
const columns = ref(['选项一', '选项二', '选项三', '选项四', '选项五'])
</script>

示例二:多级联动选择器

通过 column-change 回调函数实现省市区三级联动,当某一列切换时动态更新后续列的数据源。

vue
<template>
  <wd-picker
    label="省市区选择"
    v-model="value"
    :columns="columns"
    :column-change="onChangeDistrict"
    @confirm="handleConfirm"
  />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { PickerViewColumnChange } from '@/uni_modules/wot-ui-plus/components/wd-picker-view/types'

const value = ref(['110000', '110100', '110102'])

// 模拟省市区数据
const district: Record<string, Array<{ label: string; value: string }>> = {
  0: [
    { label: '北京市', value: '110000' },
    { label: '广东省', value: '440000' }
  ],
  110000: [{ label: '北京市', value: '110100' }],
  440000: [
    { label: '广州市', value: '440100' },
    { label: '深圳市', value: '440300' },
    { label: '珠海市', value: '440400' }
  ],
  110100: [
    { label: '东城区', value: '110101' },
    { label: '西城区', value: '110102' },
    { label: '朝阳区', value: '110105' }
  ],
  440100: [
    { label: '荔湾区', value: '440103' },
    { label: '越秀区', value: '440104' },
    { label: '海珠区', value: '440105' }
  ],
  440300: [
    { label: '罗湖区', value: '440303' },
    { label: '福田区', value: '440304' }
  ],
  440400: [
    { label: '香洲区', value: '440402' },
    { label: '斗门区', value: '440403' }
  ]
}

// 初始化数据源
const columns = ref([
  district[0],
  district[district[0][0].value],
  district[district[district[0][0].value][0].value]
])

const onChangeDistrict: PickerViewColumnChange = (pickerView, selects, columnIndex, resolve) => {
  const item = (selects as Record<string, any>[])[columnIndex]
  if (columnIndex === 0) {
    // 第一列变化,更新第二列和第三列
    pickerView.setColumnData(1, district[item.value])
    pickerView.setColumnData(2, district[district[item.value][0].value])
  } else if (columnIndex === 1) {
    // 第二列变化,更新第三列
    pickerView.setColumnData(2, district[item.value])
  }
  resolve()
}

function handleConfirm({ value }: any) {
  console.log('选中值:', value)
}
</script>

示例三:多列选择器

传入二维数组实现多列独立选择,每列可独立滚动选中。

vue
<template>
  <wd-picker
    label="学校与专业"
    v-model="value"
    :columns="columns"
    :display-format="displayFormat"
    @confirm="handleConfirm"
  />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { PickerDisplayFormat } from '@/uni_modules/wot-ui-plus/components/wd-picker/types'
import type { ColumnItem } from '@/uni_modules/wot-ui-plus/components/wd-picker-view/types'

const value = ref(['中山大学', '软件工程'])

const columns = ref([
  ['中山大学', '中南大学', '华南理工大学'],
  ['计算机科学与技术', '软件工程', '通信工程', '法学', '经济学']
])

// 自定义展示格式
const displayFormat: PickerDisplayFormat = (items) => {
  return (items as ColumnItem[])
    .map((item) => item.label)
    .join(' - ')
}

function handleConfirm({ value }: any) {
  console.log('选中值:', value)
}
</script>

示例四:确认前校验

通过 before-confirm 函数在确认前执行异步校验,校验不通过时阻止确认并显示提示。

vue
<template>
  <wd-picker
    label="需要校验的选择"
    v-model="value"
    :columns="columns"
    :before-confirm="beforeConfirm"
    @confirm="handleConfirm"
  />
  <wd-toast />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { useToast } from '@/uni_modules/wot-ui-plus'
import type { PickerBeforeConfirm } from '@/uni_modules/wot-ui-plus/components/wd-picker/types'

const toast = useToast()
const value = ref('')

const columns = ref(['选项一', '选项二', '选项三', '选项四', '选项五'])

const beforeConfirm: PickerBeforeConfirm = (value, resolve, picker) => {
  // 设置加载状态
  picker.setLoading(true)
  setTimeout(() => {
    picker.setLoading(false)
    // 模拟校验逻辑
    if (value === '选项二' || value === '选项三') {
      resolve(false)
      toast.error('校验不通过,请重新选择')
    } else {
      resolve(true)
    }
  }, 1000)
}

function handleConfirm({ value }: any) {
  console.log('确认选中:', value)
}
</script>

示例五:内联选择器 wd-picker-view 与可清空功能

wd-picker-view 直接嵌入页面中使用,实时响应变化,同时展示 wd-pickerclearable 可清空功能。

vue
<template>
  <!-- wd-picker-view 内联使用 -->
  <view class="picker-view-wrapper">
    <wd-picker-view
      v-model="pickerViewValue"
      :columns="pickerViewColumns"
      @change="handleChange"
    />
    <text>当前选中值: {{ pickerViewValue }}</text>
  </view>

  <!-- wd-picker 可清空功能 -->
  <wd-picker
    label="可清空选择"
    v-model="clearableValue"
    :columns="clearableColumns"
    clearable
    @clear="handleClear"
    @confirm="handleConfirm"
  />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { useToast } from '@/uni_modules/wot-ui-plus'

const toast = useToast()

// wd-picker-view 示例
const pickerViewValue = ref('选项一')
const pickerViewColumns = ref([
  { label: '选项一', value: '1' },
  { label: '选项二', value: '2' },
  { label: '选项三(禁用)', value: '3', disabled: true },
  { label: '选项四', value: '4' },
  { label: '选项五', value: '5' }
])

function handleChange({ value }: any) {
  console.log('picker-view 值变化:', value)
}

// wd-picker 可清空示例
const clearableValue = ref('选项二')
const clearableColumns = ref(['选项一', '选项二', '选项三', '选项四'])

function handleClear() {
  clearableValue.value = ''
  toast.success('已清空')
}

function handleConfirm({ value }: any) {
  console.log('确认选中:', value)
}
</script>

<style scoped>
.picker-view-wrapper {
  background: #fff;
  padding: 16px;
  border-radius: 8px;
}
</style>

注意事项

  • 数据源格式columns 支持一维数组(单列)和二维数组(多列),数组元素可以是字符串、数字或 ColumnItem 对象(包含 valuelabeldisabled 字段)。不能混用原始值和对象类型,否则会抛出异常。
  • 多级联动异步处理column-change 回调函数支持同步和异步两种模式。如果函数参数少于 4 个则为同步调用;如果参数为 4 个(包含 resolve),则需要在异步操作完成后调用 resolve() 通知组件更新完成。
  • 禁用选项的自动修正:当选中项被标记为 disabled 时,组件会自动寻找距离最近的未禁用选项进行替代。如果该列全部禁用,则保持当前位置不变。
  • 滑动中确认处理:当用户快速滚动后立即点击确认按钮,组件会等待滚动动画结束后再执行确认操作,确保获取到最终的选中值。
  • 取消时的数据回滚:点击取消按钮后,wd-picker 会将数据源回滚到弹窗打开前的状态,避免多级联动场景下数据源不一致。
  • displayFormat 类型校验displayFormat 必须是函数类型,否则会在控制台输出错误提示。
  • immediateChange 平台限制immediate-change 属性仅在微信小程序和支付宝小程序中生效,其他平台会在滚动动画结束后触发 change 事件。
  • rootPortal 使用场景:当选择器弹窗在 fixed 定位元素内部或某些特殊布局中无法正常显示时,可以设置 root-portal 为 true,将弹窗从当前 DOM 层级中脱离出来。
  • wd-picker-view 必须传入 modelValuewd-picker-viewmodelValue 是必填属性,即使初始值可以为空字符串或空数组也必须显式绑定。
  • columns 为空时的处理:当 columns 被设置为空数组时,组件会自动清空 pickerValueshowValue,避免显示异常。
  • 自定义 key 名映射:当数据源的字段名不是默认的 valuelabel 时,可以通过 valueKeylabelKey 属性进行自定义映射。
  • 表单校验配合:使用 wd-picker 进行表单校验时,必须设置 prop 属性与 wd-form-itemprop 对应,同时通过 rules 属性传入校验规则。

📖 Released under the MIT License