1.小程序是和后台管理系统配套使用,在后台管理系统中,级联选择器可以选择任意一级,在小程序中也需要做到选择任意一级
2.翻看了小程序提供的组件,好像并不能直接满足需求,就对组件和数据进行了改造
3.效果图
5
4.在页面中手动添加了一行,请选择,
5.js页面
Page({
data: {
multiArray: [
['无脊柱动物', '脊柱动物'],
['请选择', '扁性动物', '线形动物', '环节动物', '软体动物', '节肢动物'],
['请选择']
], // 展示的数据所存放的数据
allArray: [
{
name: '无脊柱动物',
id: 100,
children: [{
name: '扁性动物',
id: 101,
children: [{
name: '猪肉绦虫',
id: 1001
},
{
name: '吸血虫',
id: 1002
},
]
},
{
name: '线形动物',
id: 102,
children: [{
name: '蛔虫',
id: 1005
}]
},
{
name: '环节动物',
id: 103,
children: [{
name: '蚂蚁',
id: 1003
},
{
name: '蚂蟥',
id: 1004
},
]
},
{
name: '软体动物',
id: 104,
children: [{
name: '河蚌',
id: 1006
},
{
name: '蜗牛',
id: 1007
},
{
name: '蛞蝓',
id: 1008
}
]
},
{
name: '节肢动物',
id: 104,
children: [{
name: '昆虫',
id: 1009
},
{
name: '甲壳动物',
id: 1010
},
{
name: '蛛形动物',
id: 1011
},
{
name: '多足动物',
id: 1012
}
]
},
]
},
{
name: '脊柱动物',
id: 10,
children: [{
name: '鱼',
id: 11,
children: [{
name: '鲫鱼',
id: 14,
},
{
name: '带鱼',
id: 4444444,
},
]
},
{
name: '两栖动物',
id: 12,
children: [{
name: '青蛙',
id: 16,
},
{
name: '娃娃鱼',
id: 17,
},
]
},
{
name: '爬行动物',
id: 13,
children: [{
name: '蜥蜴',
id: 18,
},
{
name: '龟',
id: 19,
},
{
name: '壁虎',
id: 20,
},
]
},
]
}
], // 模拟后台返回的数据
multiIndex: [0,0,0], // 选中数据的下标
deptId: 11, // 默认选中的数据,根据数据拿到multiArray,multiIndex来做回显
},
// 选中后触发
bindMultiPickerChange: function (e) {
console.log('picker发送选择改变,携带值为', e.detail)
this.setData({
multiIndex: e.detail.value
})
},
// 列滚动后触发(静态写死的数据,方便理解)
// bindMultiPickerColumnChange: function (e) {
// // e.detail.column为滚动的列
// console.log('修改的列为', e.detail.column, ',值为', e.detail);
// var data = {
// multiArray: this.data.multiArray,
// multiIndex: this.data.multiIndex
// };
// data.multiIndex[e.detail.column] = e.detail.value;
// switch (e.detail.column) {
// // 滚动第一列
// case 0:
// switch (data.multiIndex[0]) {
// // 选中第一列第一行
// case 0:
// data.multiArray[1] = ['请选择', '扁性动物', '线形动物', '环节动物', '软体动物', '节肢动物'];
// data.multiArray[2] = ['请选择'];
// break;
// // 选中第一列第一行
// case 1:
// data.multiArray[1] = ['请选择', '鱼', '两栖动物', '爬行动物'];
// data.multiArray[2] = ['请选择'];
// break;
// }
// // 第二列,第三列回到第一行
// data.multiIndex[1] = 0;
// data.multiIndex[2] = 0;
// break;
// // 滚动第二列
// case 1:
// switch (data.multiIndex[0]) {
// case 0:
// switch (data.multiIndex[1]) {
// case 0:
// data.multiArray[2] = ['请选择'];
// break;
// case 1:
// data.multiArray[2] = ['请选择', '猪肉绦虫', '吸血虫'];
// break;
// case 2:
// data.multiArray[2] = ['请选择', '蛔虫'];
// break;
// case 3:
// data.multiArray[2] = ['请选择', '蚂蚁', '蚂蟥'];
// break;
// case 4:
// data.multiArray[2] = ['请选择', '河蚌', '蜗牛', '蛞蝓'];
// break;
// case 5:
// data.multiArray[2] = ['请选择', '昆虫', '甲壳动物', '蛛形动物', '多足动物'];
// break;
// }
// break;
// case 1:
// switch (data.multiIndex[1]) {
// case 0:
// data.multiArray[2] = ['请选择'];
// break;
// case 1:
// data.multiArray[2] = ['请选择', '鲫鱼', '带鱼'];
// break;
// case 2:
// data.multiArray[2] = ['请选择', '青蛙', '娃娃鱼'];
// break;
// case 3:
// data.multiArray[2] = ['请选择', '蜥蜴', '龟', '壁虎'];
// break;
// }
// break;
// }
// data.multiIndex[2] = 0;
// console.log(data.multiIndex, data.multiArray);
// break;
// }
// this.setData({
// multiIndex: data.multiIndex,
// multiArray: data.multiArray
// });
// this.getDataId(data.multiIndex)
// },
// 列滚动后触发(通过接口数据赋值)
bindMultiPickerColumnChange: function (e) {
console.log('修改的列为', e.detail.column, ',值为', e.detail);
var data = {
multiArray: this.data.multiArray,
multiIndex: this.data.multiIndex
};
data.multiIndex[e.detail.column] = e.detail.value;
switch (e.detail.column) {
// 滚动第一列
case 0:
data.multiArray[1] = ['请选择'];
data.multiArray[2] = ['请选择'];
this.data.allArray[data.multiIndex[0]].children.forEach(item=>{
data.multiArray[1].push(item.name)
})
// 第二列,第三列回到第一行
data.multiIndex[1] = 0;
data.multiIndex[2] = 0;
break;
// 滚动第二列
case 1:
console.log(data.multiIndex[0], data.multiIndex[1]);
if(data.multiIndex[1] == 0){
data.multiArray[2] = ['请选择'];
}else{
data.multiArray[2] = ['请选择'];
this.data.allArray[data.multiIndex[0]].children[data.multiIndex[1]-1].children.forEach(item=>{
data.multiArray[2].push(item.name)
})
console.log(data.multiArray[2]);
}
data.multiIndex[2] = 0;
console.log(data.multiIndex);
break;
}
const arr = JSON.parse(JSON.stringify(data.multiArray))
this.setData({
multiArray: arr,
multiIndex: data.multiIndex
});
console.log(this.data.multiArray);
this.getDataId(data.multiIndex)
},
// 拿到选中数据的id,根据选中数据的下标来获取数据详情
getDataId(data) {
var query = {}
if (data[1] == 0) {
query = this.data.allArray[data[0]]
}
if (data[2] == 0 && data[1] != 0) {
query = this.data.allArray[data[0]].children[data[1] - 1]
}
if (data[2] != 0 && data[1] != 0) {
query = this.data.allArray[data[0]].children[data[1] - 1].children[data[2] - 1]
}
console.log('query', query);
},
onLoad() {
// 假如有数据回显,进入页面,拿到到了id与name,来推断multiIndex,脊柱动物, 鱼, 带鱼,选中了带鱼
let multiIndex = [0,0,0]
this.data.allArray.forEach((item, index) => {
// 如果选中的是第一列的数据
if (item.id == this.data.deptId) {
multiIndex = [index, 0, 0]
// this.setData({
// multiIndex: [index, 0, 0],
// multiArray: [['无脊柱动物', '脊柱动物'], ['请选择'], ['请选择']]
// })
return
}
// 如果选中的不是第一列的数据
if (Array.isArray(item.children) && item.children.length) {
item.children.forEach((ele, inx) => {
// 如果选中的是第二列的数据
if (ele.id == this.data.deptId) {
multiIndex = [index, inx + 1, 0]
// this.setData({
// // inx + 1的目的是因为我手动添加了一行,请选择这一行,所以实际下标应该+ 1
// multiIndex: [index, inx + 1, 0],
// })
return
}
// 如果选中的不是第二列的数据
if (Array.isArray(ele.children) && ele.children.length) {
ele.children.forEach((element, ind) => {
// 如果选中的是第三列的数据
if (element.id == this.data.deptId) {
multiIndex = [index, inx + 1, ind + 1]
// this.setData({
// // inx + 1, ind + 1的目的是因为我手动添加了一行,请选择这一行,所以实际下标应该+ 1
// multiIndex: [index, inx + 1, ind + 1],
// })
return
}
})
}
})
}
})
// 在上面已经拿到了需要的下标,此时还需要拿到需要的是数据multiArray
console.log('下标',multiIndex);
// 此案例第一列固定,如果第一列也需要动态渲染,请根据接口来进行操作
let multiArray = [['无脊柱动物', '脊柱动物'], ['请选择'],['请选择']]
this.data.allArray[multiIndex[0]].children.forEach(item=>{
multiArray[1].push(item.name)
})
if(multiIndex[1] != 0){
this.data.allArray[multiIndex[0]].children[multiIndex[1]-1].children.forEach(ele=>{
multiArray[2].push(ele.name)
})
}
this.setData({
multiArray: multiArray,
multiIndex: multiIndex
})
console.log(multiArray, multiIndex);
}
// 封装多列组件,每一列都可以选择到,
// multiArray:[],默认显示的数据,点开选择器,默认能看到的数据,如果不需要回显,可以写死为默认每列的第一条数据,有几个数据表示有几列,
// multiIndex:[],表示每一列选中的数据的下标,从0开始,默认0,0,0
// bindchange: 选中后触发,携带的参数为选中数据的列的下标
// bindMultiPickerColumnChange:列滚动事件,当滚动列时触发,参数为滚动的列,与滚动到了哪一行数据的下标
// 假设现在项目需要用到三列,没一列都需要能够单独选中,则手动给每一条数据增加一项 请选择 ,此时需要注意的事情是,当通过原始数据与拿到的
// 数组下标multiIndex来拿到真实数据时,不能直接听过下标来拿到数据,因为我们手动在数据头部塞了一条数据,所以,我们需要
// 在拿到的multiIndex基础上减1来获取正确的下标,从而获取正确的数据,
// 当我们需要数据回显的时候,同样的我们先通过遍历拿到我们要回显数据的下标,注意此时拿到的下标是相对于原始数据的下标,而我们需要的小标需要在原始数据上面+1
// 通常第一列是必须选中的,所以不需要在第一列上面添加 请选择 ,
// 如果是动态的列,可以先拿到数据后来判断有几列,基本三列够用了,我这里是通过children来判断是否还有子集的,
})
6.wtnl页面
<view class="section">
<view class="section__title">多列选择器</view>
<picker mode="multiSelector" bindchange="bindMultiPickerChange" bindcolumnchange="bindMultiPickerColumnChange" value="{{multiIndex}}" range="{{multiArray}}">
<view class="picker">
当前选择:{{multiArray[0][multiIndex[0]]}},{{multiArray[1][multiIndex[1]]}},{{multiArray[2][multiIndex[2]]}}
</view>
</picker>
</view>
7.我这乱糟糟代码的解释
封装多列组件,每一列都可以选择到,
multiArray:[],默认显示的数据,点开选择器,默认能看到的数据,如果不需要回显,可以写死为默认每列的第一条数据,有几个数据表示有几列,
multiIndex:[],表示每一列选中的数据的下标,从0开始,默认0,0,0
bindchange: 选中后触发,携带的参数为选中数据的列的下标
bindMultiPickerColumnChange:列滚动事件,当滚动列时触发,参数为滚动的列,与滚动到了哪一行数据的下标
假设现在项目需要用到三列,没一列都需要能够单独选中,则手动给每一条数据增加一项 请选择 ,此时需要注意的事情是,当通过原始数据与拿到的
数组下标multiIndex来拿到真实数据时,不能直接听过下标来拿到数据,因为我们手动在数据头部塞了一条数据,所以,我们需要在拿到的multiIndex基础上减1来获取正确的下标,从而获取正确的数据,
当我们需要数据回显的时候,同样的我们先通过遍历拿到我们要回显数据的下标,注意此时拿到的下标是相对于原始数据的下标,而我们需要的小标需要在原始数据上面+1
通常第一列是必须选中的,所以不需要在第一列上面添加 请选择 ,
如果是动态的列,可以先拿到数据后来判断有几列,基本三列够用了,我这里是通过children来判断是否还有子集的,
如果不需要默认值则吧onload方法里面的代码注释掉,把multiIndex的默认值设为[],就可以了,如果哪里不正确还望指出