Fork me on GitHub

小程序:动态数据实现三级联动选择器

每个周五的下午,坐在电脑边,沏上一杯热茶,按捺不住激动的心情,为了周末的休息不上班吗?不,安静的环境是为了能够更好的学习!!!

image.png

便捷的picker

借助picker组件可以很便捷的帮我们实现省市区、日期时间、多列选择器,接下来我们来来实现一个动态数据的多列选择器。

效果图

先上效果图

效果图

交互

首先用户点击选择购车门店按钮,选择省级地区,然后通过选择的省级key充当查询条件获取市级数据,然后用选择市级后的key查询门店数据。

image.png

数据结构

后端哥们给的数据结构都一样,长这个样子
数据结构

我们使用每条数据的value用来显示,使用key 来进行请求,最后获取到选择的门店key,然后丢个后端哥们进行保存即可。

wxml

来来来,跟着我的节奏,让我看到你们的双手,哎,没让你打节奏,是敲代码 🤗️🤗️

1
2
3
4
5
6
7
8
<picker mode="multiSelector" range="{{multiArray}}" bindcolumnchange="columnchange" value="{{multiIndex}}" bindchange='pickchange'>
<view class='right' wx:if="{{multiArray[2][multiIndex[2]] && step == 0}}">
<text>请选择</text>
</view>
<view class="picker" wx:if="{{multiArray[2][multiIndex[2]] && step == 1}}">
<text>{{multiArray[2][multiIndex[2]]}}</text>
</view>
</picker>

老规矩,说下上面的代码到底干了啥

1、picker组件用来创建一个从底部弹起的滚动选择器
2、mode="multiSelector"用来声明创建的是多列选择器
3、range="" multiArray就是我们的多维数组,这次我们用来放置数据所有的名字
4、value="" multiIndex也是数组,用来表示选择的多维数组的每一项的第几个
5、bindchange是value改变触发的事件,bindcolumnchange每一列值改变时候触发的事件

如果你需要一个完美的解释,请戳 👇
完整API

两个小伙伴

bindcolumnchange

上面说了,bindcolumnchange用来绑定每一列值改变时候触发的事件,他高大威猛

1
2
3
4
5
6
7
8
9
10
11
12
13
14
columnchange(e){
console.log(e.detail) // {column: 2, value: 1}
switch (e.detail.column) { // 此时的改变列数
case 0:
// 处理逻辑
break;
case 1:
// 处理逻辑
break;
}
this.setData({
// 更新数据
})
}

column 的值表示改变了第几列(下标从0开始),value 的值表示变更值的下标

bindchange

bindchange用来绑定value改变触发的事件,他很清秀

1
2
3
4
5
6
pickchange(e){ // picker发送选择改变时候触发 通过e.detail.value获取携带的值
console.log(e.detail.value) // [0,1,2]
this.setData({
multiIndex: e.detail.value // 直接更新即可
})
}

逻辑

认识了上面的两个小伙伴,我们来缕下思路,然后来搬砖盖房。实现起来大体分为以下几步:

1、加载省级数据,处理后放置在multiArray里面,存储下原始数据并用第一个数据的key请求市级数据,拿到市级数据后做同样操作,门店同理。
2、编写columnchangepickchange函数,用来处理选择器更改时候的操作
3、页面加载后,调用获取省级数据的函数,这个函数自己会去拿市级和门店的数据

以上若不明白,可以结合最后的代码去理解

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
var app = getApp()
Page({
data: {
multiArray:[], // 三维数组数据
multiIndex:[0, 0, 0], // 默认的下标
step:0, // 默认显示请选择
},
onLoad: function (options) {
this.getProvince() // 页面加载后就调用函数 获取省级数据
},
getProvince(){ // 获取省
app.Util.ajax('/gw/app/saler/store/province_list', '', 'post').then((data) => {
var provinceList = [...data] // 放在一个数组里面
var provinceArr = data.map((item) => { return item.value }) // 获取数据里面的value值,就是只用数据的名称
this.setData({
multiArray: [provinceArr, [], []], // 更新三维数组 更新后长这样 [['江苏省', '福建省'],[],[]]
provinceList, // 省级原始数据
provinceArr // 省级所有的名称
})
var defaultCode = this.data.provinceList[0].key // 使用第一项当作参数获取市级数据
if (defaultCode){
this.setData({
currnetProvinceKey: defaultCode // 保存在当前的省级key
})
this.getCity(defaultCode) // 获取市级数据
}
})
},
getCity(code){ // 获取市级数据
this.setData({
currnetProvinceKey: code // 保存当前选择的市级code
})
app.Util.ajax('/gw/app/saler/store/city_list', { provinceCode: code }, 'post', { 'content-type': 'application/x-www-form-urlencoded' }).then((data) => {
var cityArr = data.map((item) => { return item.value })
var cityList = [...data]
this.setData({
multiArray: [this.data.provinceArr, cityArr, []], // 更新三维数组 更新后长这样 [['江苏省', '福建省'], ['徐州市'], []]
cityList, // 保存下市级原始数据
cityArr // 市级所有的名称
})
var defaultCode = this.data.cityList[0].key // 用第一个获取门店数据
if (defaultCode){
this.setData({
currnetCityKey: defaultCode // 存下当前选择的城市key
})
this.getStore(defaultCode) // 获取门店数据
}
})
},
getStore(code){
this.setData({
currnetCityKey: code // 更新当前选择的市级key
})
app.Util.ajax('/gw/app/saler/store/store_list', { cityCode: code }, 'post', { 'content-type': 'application/x-www-form-urlencoded' }).then((data) => {
var storeList = [...data]
var storeArr = data.map((item) => { return item.value})
this.setData({
multiArray: [this.data.provinceArr, this.data.cityArr, storeArr], // 重新赋值三级数组 此时的数组大概是这样 [['江苏省', '福建省'], ['徐州市'], ['徐州第一门店','徐州第二门店']]
storeList, // 保存下门店原始数据
storeArr // 保存下门店名称,可以不保存
})
})
},
columnchange(e){ // 滚动选择器 触发的事件
var column = e.detail.column // 当前改变的列
var data = {
multiIndex: JSON.parse(JSON.stringify(this.data.multiIndex)),
multiArray: JSON.parse(JSON.stringify(this.data.multiArray))
}
data.multiIndex[column] = e.detail.value; // 第几列改变了就是对应multiIndex的第几个,更新它
switch(column){ // 处理不同的逻辑
case 0: // 第一列更改 就是省级的更改
var currentProvinceKey = this.data.provinceList[e.detail.value].key
if (currentProvinceKey != this.data.currnetProvinceKey){ // 判断当前的key是不是真正的更新了
this.getCity(currentProvinceKey) // 获取当前key下面的市级数据
}
data.multiIndex[1] = 0 // 将市默认选择第一个
break;
case 1: // 市发生变化
var currentCitykey = this.data.cityList[e.detail.value].key
if (currentCitykey != this.data.currnetCityKey){ // 同样判断
this.getStore(currentCitykey) // 获取门店
}
data.multiIndex[2] = 0 // 门店默认为第一个
break;
}
this.setData(data) // 更新数据
},
pickchange(e){
this.setData({
step: 1, // 更新,用来选择用户选中的门店
multiIndex: e.detail.value // 更新下标字段
})
},
submit(){ // 保存的时候 获取当前选择门店的key 丢给后端开发即可
var storeCode = this.data.storeList[this.data.multiIndex.length - 1].key
}
})

总结

1、使用picker组件实现多列选择器还是很简单的,我们只需要将处理逻辑放在高大威猛的bindcolumnchange里面就行了。

2、可以将一些公用的函数封装在Util文件里面,如上面代码的ajax就是放在里面的。

3、还没想好,凑字数吧。

本文作者:Orton Zhang

本文链接:http://ortonzhang.com/2018/11/27/mini-program-picker/

版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!