当前位置:网站首页>【Taro】小程序picker动态获取数据
【Taro】小程序picker动态获取数据
2022-07-23 12:08:00 【web老猴子】
在小程序中,picker选择器提供了几种基础的数据格式,如时间,日期,地区等,已经基本满足绝大多数需求了。
但面对脑洞打开的客户和产品经理,官方也留给了我们个性化的空间,在picker属性中,将值设定为multiSelector,再传入一个长度不限二维数组数据,就实现了一个个性化的多项选择器。
数据量不大的时候,我们可以直接要求后端传一个长度为3或者更长的二维数组,塞入到range中。但大多联动选择器需求都是产品分类,自定义的地区数据等,此类的数据量都非常大,而且是越来越大,一次将数据全部请求过来,可能就不太合适了。
比如一个产品分类数据有一级分类,二级,还不是特别多,但里面还有三级,四级分类,这数据量就成集合增加,再加上携带的相关数据,可能一个接口就轻则100多kb,重则500+kb,这时候一级一级的获取就显得很有必要了。
一、先看逻辑
逻辑大概就是以下这样,黄色方块上为赋值,下为选择。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WCdhYOZl-1658392588806)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d0790c78af4c436f8725d3888be77795~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]
一般进入页面时会有2种状态,picker有值或空值,也就是新建表单的时候是空值,修改的时候是有值并需要回显。
展示
数据接口
getRangeData({parentCode:''}: 传入code获得下级数据列表,不传返回顶级数据列表
- 不管怎么样,第一步都要通过后端提供的接口(
getRangeData({parentCode:''}))获取第一列数据c1。 - 如果是新建,直接通过
c1的第一个值的code,即将c1[0].code传入接口获取二级数据c2,获取第三列数据也是同样操作。 - 如果是修改,这传进来一个这样的值,分别对应三列选中的值,将value的第一个值的code传入接口,即通过
selected[0].code获取第二列数据,第三列也同样操作。
const selected = [
{name: 'xxx',code: 0},
{name: 'xxx',code: 01},
{name: 'xxx',code: 012}
]
- 获取的数据都为数组,将获取到的数据组合为一个二维数组并进行赋值,即
setRange([c1,c2,c3]),这时候picker的基本功能已经算完成了,可以进行展示了。
操作
能展示的话,用户可以点击操作了,功能也就完成一半了。当滚动每一列的时候,还需要继续获取数据,动态修改下一列的数据,这里就更简单的了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJV9i95R-1658392588807)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cd90b550d4de4450b07a58d8ebe05e0c~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)]
- 通过
onColumnChange方法,获取当前滚动的列(column)和滚动到的索引值(value),则可以通过range[column][value].code获取并修改下一列的值。 - 点击确定的时候,出发
onChange方法,得到当前三列选中的索引值(value),通过这个索引和range数据组合[range[0][value[0]],range[1][value[1]],range[2][value[2]]],就得到了选中的值。
逻辑整体上就这么多,最蛋疼的就是各种组合,比较弯弯绕。
二、上代码
view部分
当值为空的时候,展示请选择,有值的时候展示选中的值
<Picker
mode="multiSelector"
range={range}
rangeKey="name"
value={pickerValue.current}
onChange={e => onChange(e)}
onColumnChange={e => colChange(e)}
>
{selected ? (
<Text>{selected.map(i => i.name).join()}</Text>
) : (
<Text style={
{ color: "#686868" }}>请选择</Text>
)}
</Picker>
js部分
在这里使用的是taro-react框架来实现这个方法,我用vue也同样实现了一次,代码结构基本上大差不差。
初始化数据
const pickerValue = useRef([0, 0, 0]); // 选择器的索引值
const [range, setRange] = useState<Array<any>>([]); // 选择器的值
const [selected, setSelected] = useState<Array<any>>([]); // 选中的值
useEffect(() => {
const init = async () => {
const p = await getRangeData({});
if (typeof params.selected === "undefined") {
// 当值为空的时候,通过分类第一个值获取下一列的值
const pp = await getRangeData({parentCode: p.data[0].code});
const ppp = await getRangeData({parentCode: pp.data[0].code});
setRange([p.data, pp.data, ppp.data]);
} else {
// 当有值的时候,通过选中的值获取下一列的值
const s = params.selected
const pp = await getRangeData({parentCode: s[0].code});
const ppp = await getAddrList({parentCode: c[1].code});
setRange([p.data, pp.data, ppp.data]);
setSelected(s);
}
};
init();
}, []);
列选择
这时候,picker的默认值就成功插进去了,下一步就是切换的时候再动态获取值
const colChange = e => {
const { column, value } = e.detail;
pickerValue.current[column] = value;
if (column === 0) { // 滑动列一
let c0 = range[0][value]; // 获取列一选中的值
const p = await getRangeData({ parentCode: c0.code });
setRange(v => [v[0], p.data, v[2]]);
} else if (column === 1) {
let c1 = range[1][value]; // 同上
const p = await getRangeData({ parentCode: c1.code });
setRange(v => [v[0], v[1], p.data]);
}
};
当pciker切换的时候,获取滚动的列和位置,再通过索引得到当前列选择的值获取下列值
这里有个点需要注意,我们的
range数据是一个数组,属于引用类型,如果使用下面这种方法修改值setRange(v => { v[1] = p.data return v });可以成功修改,但无法触发页面刷新,即第二列的值不会变,必须使用深拷贝的方法来触发页面刷新
确认选择
点击确定的是,可以得到三列的索引值,并与现有range数据进行一一对应,就得到了3个选择的值,讲选中的值筛入selected中,即完成了所有功能
const onChange = e => {
let v = e.detail.value;
let s0 = range[0][v[0]];
let s1 = range[1][v[1]];
let s2 = range[2][v[2]];
setSelected([
{name: s0.name, code: s0.code}
{name: s1.name, code: s1.code}
{name: s2.name, code: s2.code}
]);
};
总结
功能比较简单,但第一次写的话有不少坑,半天才写好,又优化了半天,在这个小功能上花费了一天时间,后面其他项目有这种动态加载列表的需要,就可以用这一套方法了。
边栏推荐
猜你喜欢

vulnstack红日-4

After Effects 教程,如何在 After Effects 中创建动画?

数字化转型时代的企业数据新基建 | 爱分析报告
![[SUCTF 2018]MultiSQL(mysql预编译)](/img/ae/501b7f9c6d8259c3c799e4ff0b568b.png)
[SUCTF 2018]MultiSQL(mysql预编译)

Google Earth engine -- null value problem in image statistics

太拼了!腾讯T4大佬凌晨4点还在熬夜,竟是在整理这分布式事务笔记
10": potential combination of no code / low code and RPA Technology"/>"1+1 > 10": potential combination of no code / low code and RPA Technology

Mathematical Modeling Typesetting

【深入浅出向】从自信息到熵、从相对熵到交叉熵,nn.CrossEntropyLoss, 交叉熵损失函数与softmax,多标签分类

反转链表画图演示
随机推荐
Vinka introduces high anti-interference vk36n series touch IC: vk36n1d, vk36n2p, vk36n3b, vk36n4i, easy to use
MySQL表字段数量限制以及行大小限制
It's too hard! Tencent T4 boss was still staying up late at 4 a.m. and was actually sorting out the distributed transaction notes
After effects tutorial, how to create animation in after effects?
Unity-笔记-ILRuntime接入
Middle aged crisis, retired at the age of 35, what do migrant workers take to compete with capitalists?
Differences between LRU and LFU elimination strategies in redis
【深入浅出向】从自信息到熵、从相对熵到交叉熵,nn.CrossEntropyLoss, 交叉熵损失函数与softmax,多标签分类
Details of task switching
不想dto套dto可以这样写
Three handling strategies of deadlock
MySQL - six logs
为什么使用opengaussjdbc的时候老是出现FATAL?(标签-数据库|关键词-user)
7、 Logic of JMeter sending request
Remote system command execution
Vinka推出高抗干扰VK36N系列触摸IC:VK36N1D,VK36N2P,VK36N3B,VK36N4I 使用便利
High cost performance, high anti-interference touch IC that meets a variety of keys: vk3606d, vk3610i, vk3618i have high power voltage rejection ratio
[operation and maintenance] SSH tunneling relies on the 22 port of SSH to realize the interface service of accessing the remote server
将.calss文件转为.jar-idea篇
信箱通信-