Skip to content

Picker 选择器 - Vant 4

🎯 Picker 选择器

🎯 介绍

Picker 组件提供多个选项集合供用户选择,支持单列选择、多列选择和级联选择,通常与弹出层组件配合使用。让选择操作更加便捷!

📦 引入

通过以下方式来全局注册组件,更多注册方式请参考组件注册

js
import { createApp } from'vue'; import { Picker } from'vant'; const app = createApp(); app.use(Picker);

🎯 代码演示

🔧 基础用法

Picker 就像一个万能的选择魔法师!🎩 通过 columns 属性配置选项数据,无论是字符串还是对象数组,都能轻松驾驭。顶部栏就像一个贴心的操作台,包含标题、确认和取消按钮,让用户的每一次选择都清晰明了。

html
<template>
  <van-picker
    title="请选择城市"
    :columns="columns"
    @confirm="onConfirm"
    @cancel="onCancel"
    @change="onChange"
  />
</template>
js
import { showToast } from 'vant';

export default {
  setup() {
    const columns = [
      { text: '杭州', value: 'Hangzhou' },
      { text: '宁波', value: 'Ningbo' },
      { text: '温州', value: 'Wenzhou' },
      { text: '绍兴', value: 'Shaoxing' },
      { text: '湖州', value: 'Huzhou' },
    ];
    
    const onConfirm = ({ selectedValues }) => {
      showToast(`您选择了: ${selectedValues.join(',')}`);
    };
    
    const onChange = ({ selectedValues }) => {
      console.log(`当前选择: ${selectedValues.join(',')}`);
    };
    
    const onCancel = () => showToast('取消选择');
    
    return {
      columns,
      onChange,
      onCancel,
      onConfirm,
    };
  },
};

🎭 搭配弹出层使用

在真实的应用场景中,Picker 就像一个优雅的舞者,经常与 Popup 和 Field 组件共舞!💃 这种组合让表单填写变得更加流畅自然,用户体验倍增。

html
<template>
  <van-field
    v-model="fieldValue"
    is-link
    readonly
    label="选择城市"
    placeholder="点击选择城市"
    @click="showPicker = true"
  />
  <van-popup v-model:show="showPicker" position="bottom">
    <van-picker
      title="选择城市"
      :columns="columns"
      @confirm="onConfirm"
      @cancel="showPicker = false"
    />
  </van-popup>
</template>
js
import { ref } from 'vue';

export default {
  setup() {
    const columns = [
      { text: '杭州', value: 'Hangzhou' },
      { text: '宁波', value: 'Ningbo' },
      { text: '温州', value: 'Wenzhou' },
      { text: '绍兴', value: 'Shaoxing' },
      { text: '湖州', value: 'Huzhou' },
    ];
    
    const fieldValue = ref('');
    const showPicker = ref(false);
    
    const onConfirm = ({ selectedValues, selectedOptions }) => {
      showPicker.value = false;
      fieldValue.value = selectedOptions[0].text;
    };
    
    return {
      columns,
      onConfirm,
      fieldValue,
      showPicker,
    };
  },
};

🔄 双向绑定

想要实现数据的双向同步?v-model 就是你的最佳伙伴!🤝 它就像一座桥梁,连接着数据和视图,让选择状态与数据保持完美同步。

html
<template>
  <van-picker
    v-model="selectedValues"
    title="城市选择"
    :columns="columns"
  />
</template>
js
import { ref } from 'vue';

export default {
  setup() {
    const columns = [
      { text: '杭州', value: 'Hangzhou' },
      { text: '宁波', value: 'Ningbo' },
      { text: '温州', value: 'Wenzhou' },
      { text: '绍兴', value: 'Shaoxing' },
      { text: '湖州', value: 'Huzhou' },
    ];
    
    const selectedValues = ref(['Wenzhou']);
    
    return {
      columns,
      selectedValues,
    };
  },
};

📊 多列选择

需要同时选择多个维度的数据?多列选择就像一个多功能工具箱!🧰 通过二维数组配置,轻松实现复杂的组合选择,比如选择工作日和时间段。

html
<template>
  <van-picker
    title="选择时间"
    :columns="columns"
    @confirm="onConfirm"
  />
</template>
js
import { showToast } from 'vant';

export default {
  setup() {
    const columns = [
      // 第一列:星期
      [
        { text: '周一', value: 'Monday' },
        { text: '周二', value: 'Tuesday' },
        { text: '周三', value: 'Wednesday' },
        { text: '周四', value: 'Thursday' },
        { text: '周五', value: 'Friday' },
      ],
      // 第二列:时间段
      [
        { text: '上午', value: 'Morning' },
        { text: '下午', value: 'Afternoon' },
        { text: '晚上', value: 'Evening' },
      ],
    ];
    
    const onConfirm = ({ selectedValues }) => {
      showToast(`选择了:${selectedValues.join(' ')}`);
    };
    
    return { columns, onConfirm };
  },
};

🌊 级联选择

级联选择就像一个智能导航系统!🗺️ 根据上级选择自动展示下级选项,让复杂的层级选择变得井然有序。省市区选择就是最经典的应用场景。

html
<template>
  <van-picker
    title="选择地区"
    :columns="columns"
    @confirm="onConfirm"
  />
</template>
js
import { showToast } from 'vant';

export default {
  setup() {
    const columns = [
      {
        text: '浙江',
        value: 'Zhejiang',
        children: [
          {
            text: '杭州',
            value: 'Hangzhou',
            children: [
              { text: '西湖区', value: 'Xihu' },
              { text: '余杭区', value: 'Yuhang' },
            ],
          },
          {
            text: '温州',
            value: 'Wenzhou',
            children: [
              { text: '鹿城区', value: 'Lucheng' },
              { text: '瓯海区', value: 'Ouhai' },
            ],
          },
        ],
      },
      {
        text: '福建',
        value: 'Fujian',
        children: [
          {
            text: '福州',
            value: 'Fuzhou',
            children: [
              { text: '鼓楼区', value: 'Gulou' },
              { text: '台江区', value: 'Taijiang' },
            ],
          },
          {
            text: '厦门',
            value: 'Xiamen',
            children: [
              { text: '思明区', value: 'Siming' },
              { text: '海沧区', value: 'Haicang' },
            ],
          },
        ],
      },
    ];
    
    const onConfirm = ({ selectedValues }) => {
      showToast(`选择的地区:${selectedValues.join(' - ')}`);
    };
    
    return { columns, onConfirm };
  },
};

💡 小贴士:级联选择的数据嵌套深度需要保持一致,如果部分选项没有子选项,可以使用空字符串进行占位。

🚫 禁用选项

有些选项暂时不可用?通过设置 disabled 属性,就像给选项贴上"暂停服务"的标签!🏷️ 用户可以看到但无法选择,体验更加友好。

html
<template>
  <van-picker
    title="选择城市"
    :columns="columns"
  />
</template>
js
export default {
  setup() {
    const columns = [
      { text: '杭州', value: 'Hangzhou', disabled: true },
      { text: '宁波', value: 'Ningbo' },
      { text: '温州', value: 'Wenzhou' },
    ];
    
    return { columns };
  },
};

⏳ 加载状态

数据还在路上?加载状态就像一个贴心的等待提示!⌛ 当选择器数据需要异步获取时,loading 属性会显示优雅的加载动画,让用户知道好东西正在准备中。

html
<template>
  <van-picker
    title="选择城市"
    :columns="columns"
    :loading="loading"
  />
</template>
js
import { ref } from 'vue';

export default {
  setup() {
    const columns = ref([]);
    const loading = ref(true);
    
    // 模拟异步数据加载
    setTimeout(() => {
      columns.value = [
        { text: '杭州', value: 'Hangzhou' },
        { text: '宁波', value: 'Ningbo' },
        { text: '温州', value: 'Wenzhou' },
      ];
      loading.value = false;
    }, 2000);
    
    return { columns, loading };
  },
};

📭 空状态

没有数据怎么办?空状态插槽就像一个友好的提示牌!📋 当数据为空时,可以自定义显示内容,让用户明白当前状况。

html
<template>
  <van-picker title="选择城市" :columns="[]">
    <template #empty>
      <div class="empty-content">
        <img src="empty-icon.png" alt="暂无数据" />
        <p>暂无可选择的城市</p>
      </div>
    </template>
  </van-picker>
</template>

🔧 自定义 Columns 的结构

数据结构不标准?没关系!通过 columns-field-names 属性,就像给数据穿上合适的衣服!👔 让任何结构的数据都能完美适配。

html
<template>
  <van-picker
    title="选择地区"
    :columns="columns"
    :columns-field-names="customFieldName"
  />
</template>
js
export default {
  setup() {
    const columns = [
      {
        cityName: '浙江',
        cities: [
          {
            cityName: '杭州',
            cities: [
              { cityName: '西湖区' },
              { cityName: '余杭区' }
            ],
          },
          {
            cityName: '温州',
            cities: [
              { cityName: '鹿城区' },
              { cityName: '瓯海区' }
            ],
          },
        ],
      },
      {
        cityName: '福建',
        cities: [
          {
            cityName: '福州',
            cities: [
              { cityName: '鼓楼区' },
              { cityName: '台江区' }
            ],
          },
          {
            cityName: '厦门',
            cities: [
              { cityName: '思明区' },
              { cityName: '海沧区' }
            ],
          },
        ],
      },
    ];
    
    const customFieldName = {
      text: 'cityName',
      value: 'cityName',
      children: 'cities',
    };
    
    return {
      columns,
      customFieldName,
    };
  },
};

API

Props

参数说明类型默认值
v-model当前选中项对应的值,控制选择器的选中状态 🎯*number[]string[]*
columns对象数组,配置每一列显示的数据,就像选择器的数据源 📊*PickerOption[]PickerOption[][]*
columns-field-names自定义 columns 结构中的字段,让数据结构更灵活 🔧object{ text: 'text', value: 'value', children: 'children' }
title顶部栏标题,为选择器添加清晰的标识 📝string-
confirm-button-text确认按钮文字,设置为空字符串可以隐藏按钮 ✅string确认
cancel-button-text取消按钮文字,设置为空字符串可以隐藏按钮 ❌string取消
toolbar-position顶部栏位置,可选值为 bottom,控制工具栏的显示位置 📍stringtop
loading是否显示加载状态,数据加载时的友好提示 ⏳booleanfalse
readonly是否为只读状态,只读状态下无法切换选项 🔒booleanfalse
show-toolbar是否显示顶部栏,控制工具栏的显示与隐藏 🎛️booleantrue
allow-html是否允许选项内容中渲染 HTML,支持富文本显示 🎨booleanfalse
option-height选项高度,支持 px``vw``vh``rem 单位,默认 px 📏*numberstring*
visible-option-num可见的选项个数,控制选择器的视窗大小 👀*numberstring*
swipe-duration快速滑动时惯性滚动的时长,单位 ms,影响滑动体验 ⚡*numberstring*

Events

事件名说明回调参数
confirm点击完成按钮时触发,确认选择操作 ✨{ selectedValues, selectedOptions, selectedIndexes }
cancel点击取消按钮时触发,取消选择操作 🚫{ selectedValues, selectedOptions, selectedIndexes }
change选中的选项改变时触发,实时响应选择变化 🔄{ selectedValues, selectedOptions, selectedIndexes, columnIndex }
click-option点击选项时触发,捕获用户的点击行为 👆{ currentOption, selectedValues, selectedOptions, selectedIndexes, columnIndex }
scroll-into v4.2.1当用户通过点击或拖拽让一个选项滚动到中间的选择区域时触发 🎯{ currentOption, columnIndex }

Slots

名称说明参数
toolbar自定义整个顶部栏的内容,完全控制工具栏样式 🎛️-
title自定义标题内容,个性化标题显示 📝-
confirm自定义确认按钮内容,打造独特的确认按钮 ✅-
cancel自定义取消按钮内容,个性化取消按钮 ❌-
option自定义选项内容,完全控制选项的显示样式 🎨option: PickerOption, index: number
columns-top自定义选项上方内容,在选择区域上方添加内容 ⬆️-
columns-bottom自定义选项下方内容,在选择区域下方添加内容 ⬇️-
empty v4.9.10自定义空状态内容,当数据为空时的友好提示 📭-

PickerOption 数据结构

键名说明类型
text选项文字内容,显示给用户的文本 📝*string
value选项对应的值,用于数据绑定的实际值 🎯*string
disabled是否禁用选项,禁用后无法选择 🚫boolean
children级联选项,用于构建多级选择结构 🌊PickerOption[]
className选项额外类名,用于自定义样式 🎨*string

方法

通过 ref 可以获取到 Picker 实例并调用实例方法,详见组件实例方法

方法名说明参数返回值
confirm停止惯性滚动并触发 confirm 事件,手动确认选择 ✅--
getSelectedOptions获取当前选中的选项,返回完整的选项对象 📋-*(PickerOption

类型定义

组件导出以下类型定义:

ts
import type {
  PickerProps,
  PickerColumn,
  PickerOption,
  PickerInstance,
  PickerFieldNames,
  PickerToolbarPosition,
  PickerCancelEventParams,
  PickerChangeEventParams,
  PickerConfirmEventParams,
} from 'vant';

PickerInstance 是组件实例的类型,用法如下:

ts
import { ref } from 'vue';
import type { PickerInstance } from 'vant';

const pickerRef = ref<PickerInstance>();
pickerRef.value?.confirm();

🎨 主题定制

样式变量

想要打造独一无二的选择器?这些 CSS 变量就是你的调色盘!🎨 通过自定义这些变量,可以轻松实现个性化的视觉效果。

名称默认值描述
--van-picker-backgroundvar(--van-background-2)选择器背景色,营造整体氛围 🎭
--van-picker-toolbar-height44px工具栏高度,控制顶部操作区域大小 📏
--van-picker-title-font-sizevar(--van-font-size-lg)标题字体大小,突出标题重要性 📝
--van-picker-title-line-heightvar(--van-line-height-md)标题行高,优化文字显示效果 📐
--van-picker-action-padding0 var(--van-padding-md)操作按钮内边距,调整按钮触摸区域 👆
--van-picker-action-font-sizevar(--van-font-size-md)操作按钮字体大小,保证按钮可读性 🔤
--van-picker-confirm-action-colorvar(--van-primary-color)确认按钮颜色,突出主要操作 ✅
--van-picker-cancel-action-colorvar(--van-text-color-2)取消按钮颜色,区分次要操作 ❌
--van-picker-option-padding0 var(--van-padding-base)选项内边距,优化选项显示效果 📦
--van-picker-option-font-sizevar(--van-font-size-lg)选项字体大小,确保选项清晰可读 🔍
--van-picker-option-text-colorvar(--van-text-color)选项文字颜色,保持良好的对比度 🎨
--van-picker-option-disabled-opacity0.3禁用选项透明度,视觉上区分可用状态 👻
--van-picker-mask-colorlinear-gradient遮罩渐变色,营造聚焦效果 🌈
--van-picker-loading-icon-colorvar(--van-primary-color)加载图标颜色,保持品牌一致性 ⏳
--van-picker-loading-mask-colorrgba(255, 255, 255, 0.9)加载遮罩颜色,提供加载状态反馈 🎭

❓ 常见问题

在桌面端无法操作组件?

参见桌面端适配

📚 相关文档

基於Vant構建的企業級移動端解決方案