当前位置: 首页 > news >正文

VantUI van-picker进阶:巧用column与插槽,实现对象数组的灵活展示与数据绑定

1. 为什么需要处理对象数组的展示?

在实际开发中,后端返回的数据往往是对象数组,每个对象包含多个属性,比如常见的id和name。而VantUI的van-picker默认只支持字符串数组的展示,这就导致了数据展示和业务逻辑处理之间的割裂。

举个例子,我们有一个请假类型的接口,返回的数据格式是这样的:

[ {id: 1, name: "年假", color: "blue"}, {id: 2, name: "病假", color: "red"}, {id: 3, name: "事假", color: "green"} ]

如果按照van-picker的默认用法,我们可能需要额外处理这个数组,提取出name属性组成新数组用于展示,同时还要维护原始数组用于获取id。这不仅增加了代码量,还容易出错。

2. 直接绑定对象数组的columns属性

VantUI的van-picker其实支持直接绑定对象数组到columns属性,只是默认情况下会调用对象的toString()方法进行展示,这显然不是我们想要的效果。

<van-picker title="请选择请假类型" show-toolbar :columns="leaveTypeList" @confirm="onConfirmType" />

这里的leaveTypeList就是我们直接从接口获取的对象数组。虽然直接这样用显示效果不理想(可能会显示[object Object]),但这已经完成了数据绑定的第一步。

我在实际项目中发现,这种直接绑定的方式有几个优势:

  1. 保持了数据的完整性,不需要额外维护一个展示用的数组
  2. 选择器内部可以访问到完整的对象数据
  3. 减少了数据转换的代码量

3. 使用插槽自定义选项展示

要让picker正确显示我们想要的属性,需要使用插槽(slot)来自定义选项的渲染方式。van-picker提供了#option插槽,可以让我们完全控制每个选项的展示内容。

<van-picker title="请选择请假类型" show-toolbar :columns="leaveTypeList" @confirm="onConfirmType" > <template #option="item"> <div class="custom-option"> <span class="name">{{ item.name }}</span> <span class="color-tag" :style="{backgroundColor: item.color}"></span> </div> </template> </van-picker>

在这个例子中,我们不仅展示了name属性,还根据color属性添加了一个颜色标签。插槽的item参数就是columns数组中的当前项,我们可以访问它的所有属性。

4. 获取选中项的完整对象数据

解决了展示问题后,我们还需要能够获取用户选择的完整对象数据。van-picker的confirm事件会返回选中的值和对应的索引。

methods: { onConfirmType(value, index) { // value就是选中的完整对象 console.log("选中的对象:", value); console.log("选中的ID:", value.id); console.log("选中的名称:", value.name); // 也可以通过索引从原始数组获取 const selectedItem = this.leaveTypeList[index]; } }

这种方式比维护两个数组(一个用于展示,一个用于存储id)要简洁得多。我在重构一个项目时,用这种方法减少了约30%的相关代码量。

5. 处理复杂数据结构的展示

有时候我们的数据结构可能更复杂,比如嵌套对象或多层级数据。这时候插槽的强大之处就体现出来了。

假设我们的数据是这样的:

[ { id: 1, info: { name: "年假", description: "带薪年假", meta: { maxDays: 15 } } } ]

我们可以这样自定义展示:

<template #option="item"> <div class="complex-option"> <h4>{{ item.info.name }}</h4> <p>{{ item.info.description }}</p> <small>最多可请{{ item.info.meta.maxDays }}天</small> </div> </template>

6. 性能优化与注意事项

虽然这种方法很灵活,但在处理大数据量时需要注意性能问题。我总结了几个优化点:

  1. 避免在插槽内进行复杂计算,可以预先处理好数据
  2. 对于超长列表,考虑使用虚拟滚动
  3. 给picker添加key属性,确保数据更新时能正确重新渲染
<van-picker :key="leaveTypeListVersion" :columns="leaveTypeList" />

当leaveTypeList更新时,同时更新leaveTypeListVersion,强制picker重新渲染。

7. 与其他Vant组件的配合使用

van-picker经常与其他表单组件配合使用。我们可以封装一个可复用的picker组件:

// PickerField.vue <template> <van-field v-model="displayValue" readonly clickable :label="label" @click="showPicker = true" /> <van-popup v-model="showPicker" position="bottom"> <van-picker :columns="options" @confirm="onConfirm" @cancel="showPicker = false" > <template #option="item"> <slot name="option" v-bind="item"> {{ item[labelKey] || item }} </slot> </template> </van-picker> </van-popup> </template> <script> export default { props: ['modelValue', 'options', 'label', 'labelKey'], emits: ['update:modelValue'], data() { return { showPicker: false, displayValue: '' } }, methods: { onConfirm(value) { this.$emit('update:modelValue', value); this.displayValue = value[this.labelKey] || value; this.showPicker = false; } } } </script>

这样使用时:

<PickerField v-model="selectedLeaveType" :options="leaveTypeList" label="请假类型" label-key="name" />

8. 实际项目中的扩展应用

在我的一个电商项目中,我们使用这种技术实现了SKU选择器。数据格式如下:

[ { skuId: "123", name: "iPhone 13", specs: [ {name: "颜色", value: "黑色"}, {name: "存储", value: "128GB"} ], price: 5999, stock: 10 } ]

对应的picker插槽:

<template #option="item"> <div class="sku-option"> <div class="specs"> <span v-for="spec in item.specs" :key="spec.name"> {{ spec.value }} </span> </div> <div class="price-stock"> <span class="price">¥{{ item.price }}</span> <span class="stock">库存{{ item.stock }}件</span> </div> </div> </template>

这种展示方式比默认的字符串展示要直观得多,用户体验也更好。

http://www.jsqmd.com/news/1085320/

相关文章:

  • 2023年——CSDN有一位持续赋能的【技术引路人】
  • 【TI毫米波雷达】从源码到部署:详解MSS与DSS协同工程的单Bin文件构建流程(以IWR6843AOP为例)
  • 终极PhotoGIMP指南:3步让GIMP拥有Photoshop的专业界面体验
  • OpCore Simplify:10分钟完成OpenCore EFI配置的黑苹果自动化工具
  • Qwen-Rapid-AIO技术方案:基于架构革新的极速AI图像编辑引擎
  • Windows系统文件iccvid.dll丢失找不到问题解决
  • 罗技鼠标宏压枪技术方案:实现精准射击的游戏体验优化
  • 禾赛激光雷达从开箱到点云可视化:一站式调试实战指南
  • 构建高效音乐聚合系统:LX Music音源配置深度解析与技术实践
  • JUnit接口自动化测试实战:从分层架构到CI/CD集成
  • ParsecVDD虚拟显示驱动0.45版本:多GPU架构重构与隐私模式技术优化
  • GD32E230 ADC注入通道实战:基于定时器触发的高精度电机相电流采样
  • Windows系统文件hid.dll丢失找不到问题解决
  • WVP-PRO本地部署实战:从零搭建海康摄像头国标接入平台
  • 【电脑端】多协议下载管理器!100MB/s,真正的全能下载器来了!一款可能让你卸载迅雷和IDM的免费下载神器
  • 饭松闹钟APP POP广告 世界杯版本记录
  • 01 FFmpeg:从命令行工具到核心架构的全面解析
  • 从IOU与ACC到mIoU与mAcc:图像分割模型评估指标的演进与实战解读
  • 从单应矩阵到三维姿态:Apriltag旋转检测的实战解析
  • 当RSA的“小钥匙”遇上大模数:低加密指数攻击实战剖析
  • ArduPilot开源飞控系统:从入门到实践的开发指南
  • 从零到一:Aircrack-ng实战环境搭建与核心功能初体验
  • Jarvis浏览器执行代理:内核级AI自动化技术解析
  • WindowResizer完整攻略:三步强制调整任意窗口大小,彻底解决尺寸限制烦恼
  • 从零搭建Arduino蓝牙机械臂小车:避障、App控制与硬件集成实战
  • Issues about education raised by family and teachers
  • 统一管理革命:XXMI启动器如何重塑游戏模组体验生态
  • MAA跨平台部署终极指南:Windows/Linux/macాలుOS全平台RR实战
  • 【JavaSE系列】 第九话 —— 多态实战:从“打印”到“绘图”的代码演绎
  • 跨游戏模组管理革命:XXMI启动器的技术架构与实践指南