☰
cube-ui Select 组件使用指南:基于 Picker 的移动端单项选择器
2026/9/25 8:04:31 网站建设 项目流程
  • 前端
  • UI组件
  • 移动开发

【免费下载链接】cube-ui

:large_orange_diamond: A fantastic mobile ui lib implement by Vue

项目地址:https://gitcode.com/gh_mirrors/cu/cube-ui
点击查看免费下载

导读

本文围绕 cube-ui(基于 Vue 的移动端 UI 组件库)中的cube-select组件展开,它是组件库为“单项选择”场景提供的高层封装:只需要传入options选项数组并通过v-model双向绑定,即可获得一个点击后弹出 Picker 选择器的移动端选择控件。读完本文,你将掌握cube-select的基本用法、完整 Props/事件配置、options对象化传参方式,并理解它与 Picker、create-api 之间的底层协作关系,能够在表单、筛选等真实业务场景中直接落地使用。

注意:本文描述的 Select 组件为 1.5.0 版本新增特性。

Select 组件是什么

cube-select是 cube-ui 提供的单选选择组件,面向“从一组预设选项中挑选一个值”的常见交互。它本质上是Picker 组件的展示层封装:页面上呈现一个可点击的选择框,内部文本显示当前选中项;点击后面向用户弹出底部选择器(Picker)完成单选,选择结果通过v-model回写。

由于该组件依赖 Picker 组件,而 Picker 组件是基于 create-api 实现(组件库内部通过$createPicker命令式 API 动态实例化),因此在使用前请确保你了解 create-api 的机制——这是理解 Select 底层行为的前提。

在源码层面,Select 组件位于 src/components/select/select.vue,其在created钩子中直接调用this.$createPicker({...})创建内部 Picker 实例,并将自身 Props(title、data、selectedIndex、cancelTxt、confirmTxt)与事件(select、cancel)桥接给 Picker,二者形成“视图层 + 选择器层”的组合结构。

基本用法

最小示例

对 Select 组件,你需要传入options定义各个选项,选择的结果则绑定在v-model上:

<cube-select v-model="value" :options="options"> </cube-select>
export default { data() { return { options: [2013, 2014, 2015, 2016, 2017, 2018], value: 2016 } } }

组件渲染后,选择框内会直接显示当前选中值2016;点击选择框弹出 Picker,选择新值后value被更新,选择框文本随之同步刷新。这一行为在单元测试 test/unit/specs/select.spec.js 中也有覆盖(should render correct contents用例验证了.cube-select-text文本与传入 value 一致)。

options 的两种定义方式

options接受一个数组,支持两种元素形式:

  1. 原始值:如2014这类非对象元素。组件内部会自动将其转化为{ value: 2014, text: 2014 },即文案与值相同;
  2. 对象:{ value, text }形式,其中text为选项文案,value为选项值,二者可分离。

该转换逻辑位于 src/components/select/select.vue 的adaptOptions计算属性中:

adaptOptions() { return [this.options.map(item => { if (typeof item !== 'object') { item = { value: item, text: item } } return item })] }

可以看到返回值被包成[ ... ]单层数组结构,这是为了直接适配 Picker 的data格式(Picker 支持多列数据,Select 作为单选只需一列)。最终传入 Picker 的数据即为“标准化后的单列选项”。

配置与事件

完整配置示例

Select 支持选择器标题(title)、占位符(placeholder)、自动弹出选择器(autoPop)、禁用(disabled)等配置,并支持自定义取消/确认按钮文案:

<cube-select v-model="value" :title="title" :options="options" :placeholder="placeholder" :auto-pop="autoPop" :disabled="disabled" cancelTxt="Cancel" confirmTxt="Confirm" @change="change"> </cube-select>
export default { data() { return { options: [2013, 2014, 2015, 2016, 2017, 2018], value: 2016, title: '入职时间', placeholder: '请选择入职时间', autoPop: false, disabled: false } }, methods: { change(value, index, text) { console.log('change', value, index, text) } } }

该示例与官方示例页 example/pages/select.vue 保持一致(示例页中为英文文案Entry time/Please choose entry time)。

change 事件的触发时机

需要注意的一点是,change事件在直接赋值修改 value 时不会触发,只会在“通过选择器选择导致修改”时触发。如果你只是想监听 value 的改变,请直接监听 value(例如用watch)。

源码中selectHandler明确体现了这一约定(src/components/select/select.vue):

selectHandler(selectedVal, selectedIndex, selectedText) { this.hided() if (selectedVal[0] !== this.value) { this.$emit(EVENT_INPUT, selectedVal[0]) this.$emit(EVENT_CHANGE, selectedVal[0], selectedIndex[0], selectedText[0]) } }

即仅在“新选中值!==当前 value”时才派发input与change;同时,命令式修改 value 时只触发 Vue 的响应式更新(选择框文本变化),不会走selectHandler。示例页中的modify方法(this.value = 2014)正是这种“直接赋值”的演示。

占位文案与未选中状态

当 value 在 options 中找不到对应项(或未设置 value)时,valueIndex计算结果为-1,此时selectedText为空,组件展示占位符:

selectedText() { return this.valueIndex !== -1 ? this.adaptOptions[0][this.valueIndex].text : '' }

模板层根据selectedText是否为空,在.cube-select-text(选中态)与.cube-select-placeholder(占位态)之间切换,占位文案默认来自 locale 配置(中英文环境下默认分别为请选择/Please select),见 src/locale/lang/zh-CN.js 与 src/locale/lang/en-US.js。

Props 配置

主配置项

| 参数 | 说明 | 类型 | 可选值 | 默认值 | | - | - | - | - | - | | options | 选项 | Array | - |[]| | v-model | 选中的值 | Any | - | - | | placeholder | 占位文案 | String | - |'请选择'(locale) | | autoPop | 是否自动弹出选择器 | Boolean | true/false |false| | disabled | 是否禁用 | Boolean | true/false |false| | title | 选择器的标题 | String | - |'请选择'(locale) | | cancelTxt | 选择器的取消按钮文案 | String | - |'取消'(locale) | | confirmTxt | 选择器的确认按钮文案 | String | - |'确认'(locale) |

各 Props 的声明与默认值可以在 src/components/select/select.vue 的props块中直接核对。注意:placeholder、title、cancelTxt、confirmTxt在源码中的默认值为空字符串'',实际展示时会通过 locale mixin($t)回退到多语言文案(如selectText、cancel、ok),因此上表默认值标注的是最终生效文案。

options 子配置项

| 参数 | 说明 | 类型 | 可选值 | 示例 | | - | - | - | - | - | | value | 该选项的值 | Any | - | - | | text | 该选项的文案 | String | - | - |

你可以将每个选项定义成一个对象,其中text为选项文案、value为选项的值;若没有将选项定义为对象(比如2014),组件内部会把它转换成{ value: 2014, text: 2014 }。

高级配置:disabled 与 autoPop

  • disabled:置为true后,点击选择框不会弹出 Picker。源码中showPicker()会先做拦截:
showPicker() { if (this.disabled) { return } this.picker.show() this.active = true this.$emit(EVENT_PICKER_SHOW) }

同时模板会为根元素添加cube-select_disabled类,通过 stylus 样式(src/components/select/select.vue 的<style>块)置灰文字与背景,并设置cursor: not-allowed。

  • autoPop:置为true后,组件在created钩子中自动调用showPicker(),即页面一加载就弹出选择器,适合强引导场景:
created() { this.picker = this.$createPicker({ ... }) this.autoPop && this.showPicker() }

事件

| 事件名 | 说明 | 参数1 | 参数2 | 参数3 | | - | - | - | - | - | | input | 在选择时,如果选择的值改变了派发 | 选中项的值 | - | - | | change | 在选择时,如果选择的值改变了派发 | 选中项的值 | 选中项的索引 | 选中项的文案 | | picker-show | 使用的 Picker 显示的时候派发 | - | - | - | | picker-hide | 使用的 Picker 隐藏的时候派发(确定或取消都会派发) | - | - | - |

各事件在源码中的派发点:

  • input/change:在selectHandler中,当选中的值与当前 value 不同时派发(src/components/select/select.vue);
  • picker-show:showPicker()弹出 Picker 时派发;
  • picker-hide:Picker 隐藏时派发——无论是点击确认(selectHandler内调用hided())还是点击取消(cancel事件绑定到hided),都会触发:
$events: { select: 'selectHandler', cancel: this.hided }

因此picker-hide是“确定或取消都会派发”的。事件触发链路在单元测试 test/unit/specs/select.spec.js 中有验证:点击选择框 →vm.picker.scrollTo(0, 1)滚动到新选项 → 点击.cube-picker-confirm确认后change回调被调用一次。

底层原理:Select 与 Picker、create-api 的协作

依赖关系链

Select 不是独立实现选择器 UI,而是复用组件库的 Picker 能力。组件注册入口 src/modules/select/index.js 说明了完整依赖:

import Picker from '../../components/picker/picker.vue' import Select from '../../components/select/select.vue' import addPicker from '../picker/api' import Locale from '../../common/locale' Select.install = function (Vue) { Vue.component(Picker.name, Picker) Vue.component(Select.name, Select) Locale.install(Vue) addPicker(Vue, Picker) }

即使用Select时,会同时注册cube-picker组件与$createPickerAPI;Select.Picker = Picker也暴露了 Picker 组件引用。

create-api 机制

$createPicker来自组件库的 create-api 体系:addPicker(src/modules/picker/api.js)通过createAPI(Vue, Picker, ['select', 'value-change', 'cancel', 'change'])注册命令式创建 API,底层依赖vue-create-api库(src/common/helpers/create-api.js)。Select 内部即利用该 API 在运行时动态实例化 Picker,并把自己的配置透传过去。

数据流向

  1. options经adaptOptions标准化为单列数据;
  2. value经valueIndex计算出当前选中项的索引(找不到时为 -1),并通过picker.setData(adaptOptions, index)同步给 Picker 的滚轮位置;
valueIndex() { const val = this.value const index = findIndex(this.adaptOptions[0], (item) => { return item.value === val }) this.picker && this.picker.setData(this.adaptOptions, index !== -1 ? [index] : [0]) return index }
  1. 用户在 Picker 滚轮中选择并点击确认后,Picker 派发select事件,selectHandler收到(selectedVal, selectedIndex, selectedText)数组,经[0]取值后更新v-model并派发change;
  2. 与此同时,valueIndex的 setData 调用保证外部修改 value 时 Picker 滚轮位置同步刷新。

Picker 组件本身基于cube-popup(底部弹出面板)与 better-scroll(滚轮滚动)实现,详见 src/components/picker/picker.vue,其确认/取消/滚动逻辑由pickerMixin、basicPickerMixin等 mixin 提供。

样式定制

Select 根元素类名为cube-select,附带三种状态类:

  • cube-select_active:Picker 弹出时的高亮态(边框激活色 + 右侧箭头旋转 180°);
  • cube-select_disabled:禁用态(文字/背景置灰 +cursor: not-allowed);
  • 内部元素:.cube-select-text(选中文案)、.cube-select-placeholder(占位文案)、.cube-select-icon(右侧箭头)。

这些样式由 src/components/select/select.vue 的 stylus<style>块定义,使用了组件库统一的variable.styl变量(如$select-color、$select-bgc、$select-border-color、$select-placeholder-color等)与border-1pxmixin(1px 边框方案),因此你可以通过覆盖这些 stylus 变量或直接追加 CSS 进行主题化定制。

小结

cube-select以极简的 API(options+v-model)完成了移动端单选的完整交互闭环:内部标准化选项、桥接 Picker 弹出层、同步选中索引、按“值是否变化”精确派发事件。实践要点可归纳为:

  1. 选项标准化:对象形式的{ value, text }可分离文案与值,原始值会自动补全为同值同文案;
  2. 事件时机:change/input仅在选择引发的值变化时触发,直接赋值请监听 value;
  3. 展示态管理:未匹配到选中值时显示占位文案,disabled与autoPop分别控制交互与自动弹出;
  4. 扩展基础:理解其底层依赖(Picker + create-api),可让你在需要更复杂的多列、级联选择时平滑迁移到 Picker 与 CascadePicker 组件。
  • 前端
  • UI组件
  • 移动开发

【免费下载链接】cube-ui

:large_orange_diamond: A fantastic mobile ui lib implement by Vue

项目地址:https://gitcode.com/gh_mirrors/cu/cube-ui
点击查看免费下载
上一篇:react-native-video老年记忆障碍视频研究
下一篇:零基础掌握HuggingFace Diffusers:从安装到图像生成全攻略

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询