ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

cube-ui 级联选择器 CascadePicker 完整实战指南:树形数据驱动、异步加载与 setData 动态更新

cube-ui 级联选择器 CascadePicker 完整实战指南:树形数据驱动、异步加载与 setData 动态更新 前端UI组件移动开发【免费下载链接】cube-ui:large_orange_diamond: A fantastic mobile ui lib implement by Vue项目地址https://gitcode.com/gh_mirrors/cu/cube-ui点击查看免费下载导读CascadePicker是 cube-ui 中基于Picker封装的级联选择器组件1.2.0 版本新增用于实现多列选择之间的级联联动当某一列的选项发生变化时后续各列会自动按树形数据重新填充。本文以 cascade-picker.md 为核心骨架结合 cascade-picker.vue 组件源码、api.js 的 create-api 注册逻辑、cascade-picker.spec.js 测试用例以及 cascade-picker.vue 示例页面系统讲解树形数据结构设计、API 式调用、setData动态重置、异步加载以及全部 Props / 事件 / 实例方法帮助你在移动端表单尤其是省市区地址选择场景中直接落地使用。由于该组件基于 create-api 实现使用前请先阅读 create-api 文档理解$createXxx的调用约定通过Vue.use注册后所有事件回调在 config 中以onXxx形式传入。一、级联的核心从二维数组到树形数据普通Picker的data是一个二维数组每一列对应一个固定数组各列之间互不影响而CascadePicker要求传入的是树形结构——第一列每个选项的children属性定义了切换到该选项时后续列的数据从而实现对后续列的级联变化。例如选择省市区时省切换为江苏省城市列就变为江苏省的各城市城市切换到苏州市区列就变为苏州市的各区。从源码看这种按列推进的级联填充逻辑集中在 cascade-picker.vue 的_updatePickerData(fromColumn)方法它以当前列选中的索引逐层下钻data[selectedIndex[i]].children从指定列开始把每层节点转换为{ value, text, order }结构写入pickerData[i]直到某层没有children为止随后截断多余的旧列pickerData.splice(i, ...)实现列数随数据深度动态变化。二、基本用法API 式创建与树形数据示例CascadePicker通过 create-api 在 Vue 原型上注册了$createCascadePicker(config)方法见 api.js组件实例挂载到body下调用.show()即可弹出。完整示例cube-button clickshowCascadePickerCascade Picker/cube-buttonconst cascadeData [ { value: Fruit, text: Fruit, children: [ { value: Apple, text: Apple, children: [{ value: 1, text: One }, { value: 2, text: Two }] }, { value: Orange, text: Orange, children: [{ value: 3, text: Three}, { value: 4, text: Four }] } ] }, { value: Drink, text: Drink, children: [ { value: Coffee, text: Coffee, children: [{ value: 1, text: One }, { value: 2, text: Two }] }, { value: Tea, text: Tea, children: [{ value: 1, text: One }, { value: 3, text: Three}] } ] } ] export default { mounted () { this.cascadePicker this.$createCascadePicker({ title: Cascade Picker, data: cascadeData, selectedIndex: [0, 1, 0], onSelect: this.selectHandle, onCancel: this.cancelHandle }) }, methods: { showCascadePicker() { this.cascadePicker.show() }, selectHandle(selectedVal, selectedIndex, selectedText) { this.$createDialog({ type: warn, content: Selected Item: br/ - value: ${selectedVal.join(, )} br/ - index: ${selectedIndex.join(, )} br/ - text: ${selectedText.join( )}, icon: cubeic-alert }).show() }, cancelHandle() { this.$createToast({ type: correct, txt: Picker canceled, time: 1000 }).show() } } }当第一列选中Fruit时第二列选项为Apple、Orange第二列选中Orange时第三列选项为Three、Four。示例数据同样可在 cascade.js含 Fruit / Drink / Dessert 三层树与 cascade-picker.vue 页面中找到可直接运行的完整版本。注意$createCascadePicker创建的是非单例实例源码 api.js 中cascadePickerAPI.before()会在传入单例参数时输出警告CascadePicker component can not be a singleton.对应测试见 cascade-picker.spec.js。三、地址选择器构造省市区三级树地址选择器不需要任何额外逻辑只需把省、市、区数据组装成级联树传入即可。仓库示例 example/data/area.js 提供了现成的provinceList、cityList、areaList按行政区划编码value关联组装代码如下cube-button clickshowAddressPickerAddress Picker/cube-buttonimport { provinceList, cityList, areaList } from example/data/area const addressData provinceList addressData.forEach(province { province.children cityList[province.value] province.children.forEach(city { city.children areaList[city.value] }) }) export default { mounted () { this.addressPicker this.$createCascadePicker({ title: City Picker, data: addressData, onSelect: this.selectHandle, onCancel: this.cancelHandle }) }, methods: { showAddressPicker() { this.addressPicker.show() }, selectHandle(selectedVal, selectedIndex, selectedText) { this.$createDialog({ type: warn, content: Selected Item: br/ - value: ${selectedVal.join(, )} br/ - index: ${selectedIndex.join(, )} br/ - text: ${selectedText.join( )}, icon: cubeic-alert }).show() }, cancelHandle() { this.$createToast({ type: correct, txt: Picker canceled, time: 1000 }).show() } } }这里的关键是用value作为父子关联键cityList[province.value]以省编码为 key 取到该省的城市数组areaList[city.value]同理取到区的数组。测试用例 cascade-picker.spec.js 也验证了selectedIndex: [1, 1, 3]时三个滚轮分别渲染为Drink/Tea/Four印证了索引逐列下钻的渲染结果。四、实例方法 setData重置数据与选中索引setData(data, selectedIndex)用于重置CascadePicker实例的数据和选中索引在组件隐藏或可见时都可以调用。其实现位于 cascade-picker.vue重置cascadeData与pickerSelectedIndex后重新执行_updatePickerData()底层 picker.vue 的setData会判断当前是否可见不可见时置dirty标记、可见时通过$nextTick重建滚轮并wheelTo到目标索引。cube-button clickshowSetDataPickerSetData Picker/cube-buttonexport default { mounted () { this.setDataPicker this.$createCascadePicker({ title: Set Data, onSelect: this.selectHandle, onCancel: this.cancelHandle }) }, methods: { showSetDataPicker() { // setData when the picker is invisible. this.setDataPicker.setData(cascadeData) this.setDataPicker.show() setTimeout(() { // setData when the picker is visible. this.setDataPicker.setData(addressData, [1, 1, 0]) }, 1000) }, selectHandle(selectedVal, selectedIndex, selectedText) { this.$createDialog({ type: warn, content: Selected Item: br/ - value: ${selectedVal.join(, )} br/ - index: ${selectedIndex.join(, )} br/ - text: ${selectedText.join( )}, icon: cubeic-alert }).show() }, cancelHandle() { this.$createToast({ type: correct, txt: Picker canceled, time: 1000 }).show() } } }setData也可以不传selectedIndex如setData(cascadeData)此时索引重置为空数组各列回到 0。测试用例 cascade-picker.spec.js 验证了setData(cascadeData, [1, 1, 1])后第三列数据长度与首项 value 均正确。另外通过 create-api 的$updateProps也可以响应式更新 Propsdata与selectedIndex变化会被 basic-picker.js 中的mergewatch 合并后自动调用setData测试 cascade-picker.spec.js 演示了从单列数据切换为三层树数据后滚轮数变为 3。五、异步加载数据async 属性与 change 事件当数据量太大、难以一次性生成完整级联树时可配置async: true开启异步加载在change事件中按需更新数据并且在数据更新完成之前用户点击确认是无效的。这个确认拦截由两级机制保证组件 cascade-picker.vue 的_pickerChange当async为 true 时只要滚动的不是最后一列i ! this.pickerData.length - 1就将pending置为true同时仍然向外抛出change事件底层 picker.vue 的_canConfirm()!this.pending this.wheels.every(wheel !wheel.isInTransition)任一条件不满足confirm()直接 return不触发select。当异步数据加载完成后调用setData(asyncData, asyncSelectedIndex)重新填充数据并清零pending确认按钮随即恢复有效。cube-button clickshowAsyncPickerAsync Load Data/cube-buttonimport { provinceList, cityList, areaList } from example/data/area const asyncData provinceList const asyncSelectedIndex [0, 0, 0] asyncData[0].children cityList[asyncData[0].value] asyncData[0].children[0].children areaList[asyncData[0].children[0].value] export default { mounted () { this.asyncPicker this.$createCascadePicker({ title: Async Load Data, async: true, data: asyncData, selectedIndex: asyncSelectedIndex.slice(), onSelect: this.selectHandle, onCancel: this.cancelHandle, onChange: this.asyncChangeHandle }) }, methods: { showAsyncPicker() { this.asyncPicker.show() }, asyncChangeHandle(i, newIndex) { if (newIndex ! asyncSelectedIndex[i]) { asyncSelectedIndex[i] newIndex // If the first two column is changed, request the data for rest columns. if (i 2) { // Mock async load. setTimeout(() { if (i 0) { const current asyncData[newIndex] current.children current.children || cityList[current.value] current.children[0].children current.children[0].children || areaList[current.children[0].value] asyncSelectedIndex[1] 0 asyncSelectedIndex[2] 0 } if (i 1) { const current asyncData[asyncSelectedIndex[0]].children[newIndex] current.children current.children || areaList[current.value] asyncSelectedIndex[2] 0 } this.asyncPicker.setData(asyncData, asyncSelectedIndex) }, 500) } } }, selectHandle(selectedVal, selectedIndex, selectedText) { this.$createDialog({ type: warn, content: Selected Item: br/ - value: ${selectedVal.join(, )} br/ - index: ${selectedIndex.join(, )} br/ - text: ${selectedText.join( )}, icon: cubeic-alert }).show() }, cancelHandle() { this.$createToast({ type: correct, txt: Picker canceled, time: 1000 }).show() } } }示例要点asyncChangeHandle(i, newIndex)中i是发生滚动的列序号0 起始newIndex是该列新选中的索引第 0 列变化后需要重置后两列索引为 0并为其补充 city 与 area 子数据第 1 列变化后只需补充 area 子数据并重置第 2 列索引children children || cityList[current.value]的写法避免重复赋值加载完成后通过setData一次性刷新界面。仓库示例在 cascade-picker.vue 中对cityList/areaList做了深拷贝JSON.parse(JSON.stringify(...))避免异步组装数据时污染原始引用。测试用例 cascade-picker.spec.js 也完整验证了异步链路滚动第一列后立即点击确认无效selectHandle调用次数为 0setData补充子数据后再点击确认才触发select。六、Props 配置总览| 参数 | 说明 | 类型 | 默认值 | 示例 | | - | - | - | - | - | | data | 级联选择器的树形数据用于初始化选项 | Array | [] | - | | selectedIndex | 被选中的索引值拉起选择器后显示这个索引值对应的内容 | Array | [] | [1] | | async1.8.1| 异步加载数据 | Boolean | false | - | | title | 标题 | String | | - | | subtitle1.8.1| 副标题 | String | | - | | cancelTxt | 取消按钮文案 | String | 取消 | - | | confirmTxt | 确定按钮文案 | String | 确定 | - | | swipeTime | 快速滑动选择器滚轮时惯性滚动动画的时长单位ms | Number | 2500 | - | | alias | 配置value和text的别名用法同Picker组件 | Object | {} | { value: id, text: name} | | visible1.8.1| 显示状态是否可见。v-model绑定值 | Boolean | false | false | | maskClosable1.9.6| 点击蒙层是否隐藏 | Boolean | true | true | | zIndex1.9.6| 样式 z-index 的值 | Number | 100 | - |data 子配置项| 参数 | 说明 | 类型 | 默认值 | 示例 | | - | - | - | - | - | | text | 每个选项展示的文案 | String/Number | - | - | | value | 每个选项的值 | String/Number/Boolean | - | - | | children | 当前选项的子节点数组驱动下一列数据 | Array | - | - |若干 Props 的源码依据与补充说明selectedIndex / data 的响应式联动两者定义在 basic-picker.js 中通过mergecomputed 将二者合并监听任一变化都会自动触发setData因此$createCascadePicker返回的实例支持$updateProps({ data, selectedIndex })动态切换。aliasalias.value、alias.text分别映射数据中的value、text字段源码见 basic-picker.js。测试 cascade-picker.spec.js 使用{ id, name }结构 alias: { value: id, text: name }验证了别名渲染正确。cancelTxt / confirmTxt 默认文案来自 locale当未显式传值时picker.js mixin 会回退到$t(cancel)/$t(ok)即中文环境下的取消 / 确定见 zh-CN.js这也是文档表格中默认值 取消、确定 的来源。swipeTime透传给底层 picker 的 BetterScroll 滚轮实例picker.vue控制惯性滚动动画时长。maskClosable 的默认值差异pickerMixin中默认truepicker.js而popupMixin中默认falsepopup.jsCascadePicker 同时混入二者实际生效以pickerMixin的true为准点击蒙层是否取消的逻辑见 picker.vue。zIndex默认 100通过cube-popup的:z-index透传picker.vue。visible基于 visibility.js 的v-model双向绑定visible变化会自动调用show()/hide()组件内部用isVisible中间数据避免非响应式 prop 导致 toggle 失败。七、事件与实例方法事件| 事件名 | 说明 | 参数1 | 参数2 | 参数3 | | - | - | - | - | - | | select | 点击确认按钮触发此事件 | selectedVal: 当前选中项每一列的值Array 类型 | selectedIndex: 当前选中项每一列的索引Array 类型 | selectedText: 当前选中项每一列的文案Array 类型 | | change | 滚轴滚动后触发此事件 | index: 当前滚动列次序Number 类型 | selectedIndex: 当前列选中项的索引Number 类型 | | cancel | 点击取消按钮触发此事件 | - | - |实例方法| 方法名 | 说明 | 参数1 | 参数2 | | - | - | - | - | | setData | 重置数据和选中的索引 | 级联树形数据结构Array 类型 | 每列选中的索引Array 类型 | | show | 显示 | - | - | | hide | 隐藏 | - | - |事件流转的源码路径select由底层 picker 的confirm()收集各列_values/_indexes/pickerSelectedText后发出picker.vueCascadePicker 通过_pickerSelect原样转发cascade-picker.vuechange由底层滚轮scrollEnd触发后逐级转发picker.vuecancel由取消按钮或蒙层点击触发picker.vue。事件注册方面create-api 声明的事件集合为[select, cancel, change]api.js因此在$createCascadePicker的 config 中使用onSelect/onCancel/onChange传入回调即可。测试用例 cascade-picker.spec.js 通过dispatchSwipe模拟滚轮滑动验证了三个事件均按预期触发。show()/hide()由 visibility.js mixin 提供内部维护isVisible并同步 emittoggle故同时支持visible的v-model控制。八、使用注意事项与最佳实践先注册再调用所有 create-api 组件都需Vue.use(CascadePicker)注册见 index.js注册时会同时挂载底层Picker与$createPicker、$createCascadePicker两个 APICascadePicker.Picker也被暴露为静态属性便于按需引用。不要做成单例级联选择器在不同场景需要不同数据创建时传入single true只会收到警告源码 api.js。异步模式必须成对使用async: true时change事件后必须最终调用setData结束pending状态否则确认按钮会一直失效异步数据加载期间给用户足够的视觉反馈如 loading 状态。索引越界保护_updatePickerData中pickerSelectedIndex[i] data.length的判断cascade-picker.vue会防止传入的初始索引越界导致白屏但业务侧仍应保证selectedIndex与树深度匹配。复用数据结构时注意引用共享示例页面在异步场景中对cityList/areaList做深拷贝cascade-picker.vue避免多次组装时修改原始数据。列数动态伸缩由于列数由树深度决定setData或$updateProps切换数据源后滚轮数会动态增减底层_destroyExtraWheels负责销毁多余滚轮见 picker.vue无需手动管理。九、小结CascadePicker用一份树形数据把多列联动的复杂度收敛到了children递归下钻上配合 create-api 的$createCascadePicker、setData动态重置与async异步加载足以覆盖省市区选择、多级分类、动态选项等绝大多数移动端级联场景。想进一步研究可继续阅读组件实现cascade-picker.vue底层滚轮 Pickerpicker.vue模块注册与 API 挂载index.js 与 api.js可运行示例cascade-picker.vue 与数据 cascade.js、area.js单元测试cascade-picker.spec.jscreate-api 机制create-api.md赞分享前端UI组件移动开发【免费下载链接】cube-ui:large_orange_diamond: A fantastic mobile ui lib implement by Vue项目地址https://gitcode.com/gh_mirrors/cu/cube-ui点击查看免费下载相关推荐TileMill高级技巧10个提升地图设计效率的方法TileMill高级技巧10个提升地图设计效率的方法 TileMill是一款功能强大的现代地图设计工作室基于Node.js和Mapnik构建让地图设计师能Element UI Tree 树形控件完全指南数据绑定、懒加载、勾选联动与拖拽实战Element UI Tree 树形控件完全指南数据绑定、懒加载、勾选联动与拖拽实战 导读 本文以 Element UIVue.js 2.0 UI Tool前端UI组件设计系统Formily Next 表格选择组件 SelectTable 完整实战指南单选、多选、树形数据与异步数据源Formily Next 表格选择组件 SelectTable 完整实战指南单选、多选、树形数据与异步数据源 SelectTable 是 formily/n前端UI组件上一篇GGEditor 开源项目教程下一篇终极指南如何快速安装和使用 Glasskube - Kubernetes 下一代包管理器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表