版本:"version": "2.0.0",
uniapp提供的级联选择的组件。通常用于单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景。
但在使用的时候还是遇到很多问题。这里就记录一下本人在使用2.0.0版本的uni-data-picker组件遇到的问题,以及个性化需求的实现方案。
问题1、数据从属级别错乱问题
预期希望是这样的:
实际现象如下:
显然不正确,数据已经错乱了。但是我们就是按照官网一样写法绑定了localdata,字段名称也是text,value,children了呀。为什么呢?
后来看了组件源码,好像是由于selectIndex导致。是由于接口返回的数据的id值存在重复的,导致会把id相同的数据全部查出来显示。如下:
同时也去问了官方技术人员,得到确切反馈说2.0.0版本的value值(也就是我们那个接口返回的id值)要唯一的,不能存在重复。
解决方案:
方案1: 如果返回的数据结构的id值可以改变的话,可以让后端修改之后返回。然后把id值给组件所需的value属性。
方案2:如果id值已经不能改变了,那就前端对数据进行处理,自己造一个唯一的值赋值给组件所需的value属性。
!注意: 这两种方案只能解决数据层级结构乱的问题,并不能解决标题动态展示的问题。
我的情况是第二种,值不能变,就自己处理数据。
把确保value属性值是唯一即可。
function formatData(data, level) {
level = level + 1
let result = []
if (!data.length) return []
result = data.map((item, index) => {
console.log(_id, index, level)
let obj = {
...item,
text: item.label,
value: _id++, // 仅仅用于唯一标识数据作用的,解决value值重复问题
level: level, // 标识当前属于第几个层级
children: item.children && item.children.length > 0 ? formatData(item.children, level) : []
}
return obj
})
return result
}
至此,解决数据错乱问题。
!注意:
uni-data-picker组件得到的值是绑定的每一项数据的value属性的值。 如果需要拿到原本数据的id值的话,可以在处理数据时,把原有的id值拼接上。
function formatData(data, level) {
level = level + 1
let result = []
if (!data.length) return []
result = data.map((item, index) => {
let obj = {
...item,
text: item.label,
value: item.id + '-' + _id++, // 仅仅用于唯一标识数据作用的,解决value值重复问题
level: level, // 标识当前属于第几个层级
children: item.children && item.children.length > 0 ? formatData(item.children, level) : []
}
return obj
})
return result
}
value: item.id + '-' + _id++, 这样拼接上之后,后期需要数据的时候,可以从这里获取。
问题2、当前选项的标题提示需求的实现
这是我们需求的实现。这些数据不像省市县那种,即便不用标注当前选择的是什么,也能通过显示的值可以知道。
但类似这些版本,系统版本,框架版本之类数据只有一个版本号。如果不熟悉的用户的话,根本不知道当前选择的是什么数据。因此给用户一个提示是非常必要的。
希望如下显示:
组件自身的局限性
这个版本的组件并没有提供可以动态修改当前选择项的标题。已经写死是”请选择“。
所以想要实现动态的话,只能修改源码了。但需要理清楚这个组件的逻辑,在修改,可能需要花一点时间。那有没有其他方案可以替代呢?
我们可以从pupTitle属性入手。可以利用弹框标题提示。如下
实现步骤
1、模板
<uni-data-picker
:localdata="publicImgList"
v-model="goodInfo.image_id"
placeholder="请选择镜像"
:popup-title="pupTitle"
@nodeclick="handleNodeClick">
</uni-data-picker>
2、获取数据
const publicImgList = ref([])
let _id = 0
let level = 0 // 记录当前是第几层
let pupTitle = ref('框架类型')
async function getPublicImgList() {
const res = await getPublicImageListApi()
if (res.code === 0) {
publicImgList.value = formatData(res.data, level) // 加工数据
}
}
3、加工数据
function formatData(data, level) {
level = level + 1
let result = []
if (!data.length) return []
result = data.map((item, index) => {
let obj = {
...item,
text: item.label,
value: _id++, // 仅仅用于唯一标识数据作用的,解决value值重复问题
level: level, // 标识当前属于第几个层级
children: item.children && item.children.length > 0 ? formatData(item.children, level) : []
}
return obj
})
return result
}
重要属性:level
用于记录当前的对象数据是属于第几层的数据。
经过处理后,我们就通过level属性知道第几层的数据了。
4、修改puptitle值
注意:
@nodeclick 事件得到的值是当前点击的节点的数据。我们需要去修改它下一级即将要选择什么的标题。
因此e.level是当前点击的层级。
pupTitle的值是下一级需要显示的标题
function handleNodeClick(e) {
console.log('当前是第几层:', e.level)
switch (e.level) {
case 0:
pupTitle.value = '框架版本';
break;
case 1:
pupTitle.value = '框架版本';
break;
case 2:
pupTitle.value = 'python版本';
break;
case 3:
pupTitle.value = 'cuda版本';
break;
default:
pupTitle.value = '请选择';
break;
}
}
至此,我们就可以实现我们的需求了。
完整代码
<template>
<uni-data-picker
:localdata="goodInfo.image_type===1?publicImgList:userImgList"
v-model="goodInfo.image_id"
placeholder="请选择镜像"
:popup-title="pupTitle"
@nodeclick="handleNodeClick"
>
</uni-data-picker>
</template>
<script setup>
import {onLoad} from '@dcloudio/uni-app'
import {ref} from 'vue'
import {getPublicImageListApi} from '@/api/product.js'
onLoad(async (options) => {
uni.showLoading({
title:'loading...',
})
await Promise.all([getPublicImgList()])
uni.hideLoading()
})
const publicImgList = ref([])
let _id = 0
let level = 0
let pupTitle = ref('框架类型')
// 格式化数据
function formatData(data, level) {
level = level + 1
let result = []
if (!data.length) return []
result = data.map((item, index) => {
console.log(_id, index, level)
let obj = {
...item,
text: item.label,
value: _id++, // 仅仅用于唯一标识数据作用的,解决value值重复问题
level: level, // 标识当前属于第几个层级
children: item.children && item.children.length > 0 ?formatData(item.children, level) : []
}
return obj
})
return result
}
// 获取系统镜像
async function getPublicImgList() {
const res = await getPublicImageListApi()
if (res.code === 0) {
publicImgList.value = formatData(res.data, level)
}
}
// 节点点击事件
function handleNodeClick(e) {
console.log('当前是第几层:', e.level)
switch (e.level) {
case 0:
pupTitle.value = '框架版本';
break;
case 1:
pupTitle.value = '框架版本';
break;
case 2:
pupTitle.value = 'python版本';
break;
case 3:
pupTitle.value = 'cuda版本';
break;
default:
pupTitle.value = '请选择';
break;
}
</script>
最后,这里仅仅记录本次2.0.0版本的uni-data-picker组件遇到的问题。 希望能对大家有帮助~
如果有错误地方或者可以补充的地方,欢迎大家留言。