Skip to content

PickerView 选择器视图

介绍

PickerView 选择器视图是一个嵌入页面的滚动选择器组件,用于从一组数据中选择单个或多个值。与 Picker 组件不同,PickerView 不包含弹出层,可以直接嵌入到页面中使用,适用于需要将选择器固定显示在页面某个区域的场景。

组件基于原生 picker-view 实现,支持单列选择和多列联动选择,提供了丰富的数据格式支持和灵活的列联动回调机制。通过 columnChange 属性可以实现省市区等多级联动选择功能。

核心特性:

  • 嵌入式设计 - 直接嵌入页面,无需弹出层,适合固定展示场景
  • 多列支持 - 支持单列和多列选择,可实现复杂的多级联动
  • 灵活数据格式 - 支持字符串数组、对象数组、二维数组等多种数据格式
  • 列联动回调 - 提供 columnChange 回调,支持异步数据加载和列间联动
  • 禁用选项 - 支持禁用特定选项,禁用项自动跳过选择
  • 加载状态 - 内置 loading 状态,适合异步数据场景

基本用法

单列选择

最简单的使用方式,传入一维数组作为选项数据。

vue
<template>
  <wd-picker-view v-model="value" :columns="columns" />
</template>

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

const value = ref('February')
const columns = ref(['January', 'February', 'March', 'April', 'May', 'June'])
</script>

对象数组

使用对象数组时,通过 valueKeylabelKey 指定取值字段。

vue
<template>
  <wd-picker-view
    v-model="value"
    :columns="columns"
    value-key="id"
    label-key="name"
  />
</template>

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

const value = ref(2)
const columns = ref([
  { id: 1, name: '北京' },
  { id: 2, name: '上海' },
  { id: 3, name: '广州' },
  { id: 4, name: '深圳' },
])
</script>

多列选择

传入二维数组实现多列选择,每个子数组代表一列。

vue
<template>
  <wd-picker-view v-model="value" :columns="columns" />
</template>

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

const value = ref(['February', 'February'])
const columns = ref([
  ['January', 'February', 'March', 'April', 'May', 'June'],
  ['January', 'February', 'March', 'April', 'May', 'June'],
])
</script>

多列联动

通过 columnChange 回调实现列间联动,当某一列值变化时动态更新其他列的数据。

vue
<template>
  <wd-picker-view
    v-model="value"
    :columns="columns"
    :column-change="handleColumnChange"
  />
</template>

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

const value = ref(['浙江', '杭州'])

const cityData: Record<string, string[]> = {
  '浙江': ['杭州', '宁波', '温州', '绍兴'],
  '江苏': ['南京', '苏州', '无锡', '常州'],
  '广东': ['广州', '深圳', '东莞', '佛山'],
}

const columns = ref([
  Object.keys(cityData),
  cityData['浙江'],
])

const handleColumnChange: PickerViewColumnChange = (picker, selects, index, resolve) => {
  if (index === 0) {
    // 省份变化时,更新城市列
    const province = (selects as Record<string, any>[])[0].value
    picker.setColumnData(1, cityData[province] || [], 0)
  }
  resolve()
}
</script>

禁用选项

通过 disabled 属性禁用特定选项,禁用的选项无法被选中。

vue
<template>
  <wd-picker-view v-model="value" :columns="columns" />
</template>

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

const value = ref('February')
const columns = ref([
  { label: 'January', value: 'January' },
  { label: 'February', value: 'February' },
  { label: 'March', value: 'March', disabled: true },
  { label: 'April', value: 'April' },
  { label: 'May', value: 'May', disabled: true },
  { label: 'June', value: 'June' },
])
</script>

加载状态

设置 loading 属性显示加载状态,适用于异步获取数据的场景。

vue
<template>
  <wd-picker-view
    v-model="value"
    :columns="columns"
    :loading="loading"
    loading-color="#1989fa"
  />
</template>

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

const value = ref('')
const columns = ref<string[]>([])
const loading = ref(true)

onMounted(() => {
  // 模拟异步加载
  setTimeout(() => {
    columns.value = ['选项1', '选项2', '选项3']
    value.value = '选项1'
    loading.value = false
  }, 1500)
})
</script>

自定义高度

通过 columnsHeight 属性设置选择器的高度。

vue
<template>
  <wd-picker-view
    v-model="value"
    :columns="columns"
    :columns-height="300"
  />
</template>

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

const value = ref('February')
const columns = ref(['January', 'February', 'March', 'April', 'May', 'June'])
</script>

API

Props

参数说明类型默认值
v-model选中项的值string | number | boolean | Array-
columns选择器数据,支持字符串数组、对象数组、二维数组Array[]
loading是否显示加载状态booleanfalse
loading-color加载图标颜色,十六进制格式string#4D80F0
columns-height选择器内部滚筒高度,单位 rpxnumber217
value-key选项对象中 value 对应的 keystringvalue
label-key选项对象中展示文本对应的 keystringlabel
immediate-change是否在手指松开时立即触发 change 事件booleanfalse
column-change列变化回调函数,用于实现列间联动PickerViewColumnChange-
custom-class自定义根节点样式类string-
custom-style自定义根节点样式string-

Events

事件名说明回调参数
change选中项变化时触发{ picker: PickerViewExpose, value: PickerViewValue, index: number }
pickstart开始滚动时触发-
pickend结束滚动时触发-

Methods

通过 ref 获取组件实例后可调用以下方法:

方法名说明参数返回值
getSelects获取所有列选中项-Record<string, any> | Record<string, any>[]
getValues获取所有列的选中值-PickerViewValue
getLabels获取所有列选中项的 label-string[]
getColumnData获取某一列的选项columnIndex: numberRecord<string, string>[]
getColumnsData获取所有列数据-Record<string, string>[][]
getColumnIndex获取某一列的选中项下标columnIndex: numbernumber
getSelectedIndex获取选中索引数组-number[]
setColumnData设置某一列的数据columnIndex: number, data: Array, rowIndex?: number-
resetColumns重置列数据columns: Array-

类型定义

typescript
/**
 * 列选项数据项接口
 */
interface ColumnItem {
  /** 选项值 */
  value?: string | number | boolean
  /** 选项标签 */
  label?: string
  /** 是否禁用 */
  disabled?: boolean
  [key: string]: any
}

/**
 * 选择器值类型
 */
type PickerViewValue = string | number | boolean | Array<string | number | boolean>

/**
 * 列变化回调函数类型
 */
type PickerViewColumnChange = (
  pickerView: WdPickerViewExpose,
  selects: Record<string, any> | Record<string, any>[],
  index: number,
  resolve: () => void,
) => void

/**
 * 组件暴露接口
 */
interface WdPickerViewExpose {
  getSelects: () => Record<string, any> | Record<string, any>[]
  getValues: () => PickerViewValue
  setColumnData: (columnIndex: number, data: Array, rowIndex?: number) => void
  getColumnsData: () => Record<string, string>[][]
  getColumnData: (columnIndex: number) => Record<string, string>[]
  getColumnIndex: (columnIndex: number) => number
  getLabels: () => string[]
  getSelectedIndex: () => number[]
  resetColumns: (columns: Array) => void
}

主题定制

CSS 变量

组件提供了以下 CSS 变量用于主题定制:

变量名说明默认值
--wd-picker-bg选择器背景色#ffffff
--wd-picker-mask选择器遮罩背景渐变色
--wd-picker-loading-bg加载状态背景色rgba(255, 255, 255, 0.8)
--wd-picker-column-fs选项字体大小32rpx
--wd-picker-column-color选项文字颜色#333333
--wd-picker-column-disabled-color禁用选项文字颜色#c0c4cc
--wd-picker-column-padding选项内边距0 20rpx

暗黑模式

组件已适配暗黑模式,在暗黑主题下会自动切换样式:

scss
.wot-theme-dark {
  .wd-picker-view {
    // 暗黑模式下的样式自动适配
  }
}

最佳实践

1. 异步联动加载

对于省市区等需要异步加载的场景,在 columnChange 中使用 resolve 回调:

vue
<script lang="ts" setup>
const handleColumnChange: PickerViewColumnChange = async (picker, selects, index, resolve) => {
  if (index === 0) {
    // 异步加载城市数据
    const cities = await fetchCities(selects[0].value)
    picker.setColumnData(1, cities, 0)
  }
  // 数据加载完成后调用 resolve
  resolve()
}
</script>

2. 表单集成

在表单中使用时,可以通过 getValues 方法获取当前选中值:

vue
<template>
  <wd-picker-view ref="pickerRef" v-model="value" :columns="columns" />
  <wd-button @click="handleSubmit">提交</wd-button>
</template>

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

const pickerRef = ref()
const value = ref('')

const handleSubmit = () => {
  const selectedValue = pickerRef.value?.getValues()
  const selectedLabels = pickerRef.value?.getLabels()
  console.log('选中值:', selectedValue)
  console.log('选中标签:', selectedLabels)
}
</script>

常见问题

1. 如何获取选中项的完整信息?

使用 getSelects 方法可以获取选中项的完整对象信息:

typescript
const pickerRef = ref()

// 获取选中项完整信息
const selects = pickerRef.value?.getSelects()
console.log(selects) // { label: 'xxx', value: 'xxx', ... }

2. 多列联动时如何处理异步数据?

确保在 columnChange 回调中正确使用 resolve:

typescript
const handleColumnChange: PickerViewColumnChange = (picker, selects, index, resolve) => {
  // 异步操作
  fetchData().then((data) => {
    picker.setColumnData(1, data, 0)
    resolve() // 数据准备好后调用
  })
}

3. 如何动态更新选项数据?

直接修改 columns 响应式数据即可:

typescript
// 动态更新列数据
columns.value = newColumns
移动端预览