最近的项目要求是地址选择器是自定义的地址,不能直接用全国的地址。由于小程序提供的picker组建是它内部提供的,并没有提供替换的数据的接口,遂用小程序提供的多列选择器
后台获取的数据结构是这样的{
“level”: “success”,
“message”: “获取成功”,
“data”: [
{
“name”: “广东省”,
“cityList”: [
{
“name”: “广州市”,
“areaList”: [
{
“name”: “海珠区”,
“townList”: [
“康乐村”,
“瑞宝”,
“鹭江”,
“上冲”,
“大塘”,
“七星岗”,
“后滘”
]
},
{
“name”: “天河区”,
“townList”: [
“土华”,
“东圃”,
“吉山”,
“龙岗村”
]
},
{
“name”: “白云区”,
“townList”: [
“大埔”,
“新市”,
“棠溪”
]
},
{
“name”: “番禺区”,
“townList”: [
“塘步西”,
“塘步东”,
“植村”,
“南村”,
“大石”,
“沙涌”
]
},
{
“name”: “增城区”,
“townList”: [
“新塘”
]
}
]
},
{
“name”: “东莞市”,
“areaList”: [
{
“name”: “”,
“townList”: [
“镇口”,
“大朗”
]
}
]
},
{
“name”: “深圳市”,
“areaList”: [
{
“name”: “盐田区”,
“townList”: [
“沙头角”
]
},
{
“name”: “宝安区”,
“townList”: [
“大浪”
]
},
{
“name”: “龙岗区”,
“townList”: [
“布吉”,
“横岗”,
“平湖”,
“坂田”
]
},
{
“name”: “福田区”,
“townList”: [
“八卦岭”
]
}
]
},
{
“name”: “汕头市”,
“areaList”: [
{
“name”: “龙湖区”,
“townList”: [
“龙湖工业区”
]
},
{
“name”: “潮阳区”,
“townList”: [
“谷饶”
]
},
{
“name”: “潮南区”,
“townList”: [
“峡山”,
“司马浦”,
“两英”,
“陈店”,
“成田”
]
},
{
“name”: “澄海区”,
“townList”: [
“隆都”
]
}
]
}
]
},
{
“name”: “湖北省”,
“cityList”: [
{
“name”: “武汉市”,
“areaList”: [
{
“name”: “硚口区”,
“townList”: [
“汉正街”,
“武胜路”,
“长丰乡”,
“常码头”
]
},
{
“name”: “汉阳区”,
“townList”: [
“快活岭”,
“磨山工业园”
]
},
{
“name”: “江汉区”,
“townList”: [
“经济开发区”
]
},
{
“name”: “江岸区”,
“townList”: [
“石桥”
]
}
]
}
]
},
{
“name”: “湖南省”,
“cityList”: [
{
“name”: “株洲市”,
“areaList”: [
{
“name”: “芦淞区”,
“townList”: [
“龙泉路”,
“董家段高科园”
]
},
{
“name”: “荷塘区”,
“townList”: [
“合泰”
]
}
]
}
]
},
}
实现思路有:
province,一个array存放各种省份[‘广东省’,‘北京市’]
cityList,一个objcet,存放省份对应的市{‘广东省’:[‘广州市’,‘深圳市’],‘北京市’:[‘北京市’,‘什么市’]}
countyList,一个object,存放市对应的区{‘广州市’:[‘番禺区’,‘增城区’]};
multiArray3: [[], [], []],小程序传进的多列联动的数据格式。分别对应每一列的选项。它这样设计是不能联动的。我想到的方法是每当一项改变,动态改变其他列的数据,来实现联动。
multiIndex3: [0,0,0] 小程序中用来确认选中时,显示的选项的下标。(点击确认时,必须改变为multiIndex3,从而使它显示出来,否则点击确认也无法显示相应值)
代码如下
export const mixin1={//用了vue的mixin便于其他页面也能复用
data(){return{
province:'',//存放省的数组如:['广东省','湖南省',````],arr类型
cityList:'',//放某省内的市如:{'广东省':['广州市','深圳市'],'北京市':['北京市','什么市']},obj类型
countyList:'',//{'广州市':['番禺区','增城区']}放某区市的区
multiArray3: [[], [], []],//这里multiArray3是传进多列picker的数组
multiIndex3: [0,0,0],//这里必须吐槽一下小程序的设计,我不懂为什么选择后,还要自主来更改选中项的index才行。就应该在选中时,内部自动更改相应index就好了。
}},
methods:{
bindMultiPickerColumnChange(e){
let val=e.target.value;//每一项改变时,小程序组建传来的当列选中项的index
switch (e.target.column) {
case 0://第一列改变时
let arr=this.getArr(this.province[val],this.cityList)
this.$set(this.multiArray3,1,[])//先清空multiArray3的第1项(其实这一步没必要,只是为了逻辑的完整)
this.$set(this.multiArray3,1,arr);//设置第二列数据
let arr2=this.getArr(arr[0],this.countyList);//从第二列拿出第一项中,在countyList中查找并设置第三列的数组。这么做时为了在选择第一列时,第二列也相应显示出了相应的市,并且第三列联动默认有显示
if(arr2){
this.$set(this.multiArray3,2,arr2);//设置第三组数据
}else{
this.$set(this.multiArray3,2,['-']);
}
this.$set(this.multiIndex3,0,val);//设置当前显示的下标
this.$set(this.multiIndex3,1,0);
this.$set(this.multiIndex3,2,0);//又来吐槽一下小程序,真是糟糕的设计
break;
case 1:
let arr3=this.getArr(this.multiArray3[1][val],this.countyList);
this.$set(this.multiArray3,2,[])
if(arr3){
this.$set(this.multiArray3,2,arr3)
}else{
this.$set(this.multiArray3,2,['-']);
}
this.$set(this.multiIndex3,1,val)
this.$set(this.multiIndex3,2,0);
break;
}
},
getArr(address,arr){//返回一个选中项后,对应的下级数组,例如,选中了广东省,那么就从this.cityList中找出key为广东省的value :['广州市','深圳市']
for(let p in arr){
if(address==p){
return arr[p]
}
}
},
async getAddress(){//获取传入的数据
let res=await this.$request.getData('/other/get-address-all');
this.initAddress=res
let province=[];//['广东省','广西省','湖南省']
let cityList={};//{'广东省':['广州市','深圳市']}放某省内的市
let countyList={};//{'广州市':['番禺区','增城区']}放某区市的区
if(res.data.level=='success'){//获取自主传入的地址
res.data.data.forEach((val)=>{
if(val.name!=''){
province.push(val.name);
if(val.cityList!=''){
let arr=[];
val.cityList.forEach(val1=>{
arr.push(val1.name);
if(val1.areaList!=''){
let arr2=[]
val1.areaList.forEach(val2=>{
arr2.push(val2.name)
})
countyList[val1.name]=arr2
}
})
cityList[val.name]=arr;
}
}
})
}
this.province=province;
this.cityList=cityList;
this.countyList=countyList;
this.multiArray3[0]=this.province
this.multiArray3[1]=this.getArr(this.province[0],this.cityList);
this.multiArray3[2]=this.getArr(this.multiArray3[1][0],this.countyList);
}
},
mounted() {
this.getAddress()
},
}
吃饭了再码vant的3级联动
——————————————————分界线————————————————
本处的vant组建用于h5的开发
对于组件vant的话。vant的地址选择器 详见 https://youzan.github.io/vant/#/zh-CN/area
本人尝试用vant提供的多列选择器,但是从官网上只能找到2列选择器的相关。对于3列或以上的并没有提供相应的数据格式。
遂从它的地址选择器进行入手。
初始化很简单
传进一个地址的json文件即可
(官网有完整的全国地址json)
{
province_list: {
110000: ‘北京市’,
120000: ‘天津市’
},
city_list: {
110100: ‘北京市’,
110200: ‘县’,
120100: ‘天津市’,
120200: ‘县’
},
county_list: {
110101: ‘东城区’,
110102: ‘西城区’,
110105: ‘朝阳区’,
110106: ‘丰台区’
120101: ‘和平区’,
120102: ‘河东区’,
120103: ‘河西区’,
120104: ‘南开区’,
120105: ‘河北区’,
// …
}
}
因为业务要求时自定义的地址。遂对获取下来的data进行重组数据。数据结构跟最上方后台获取的一致。
思路:vant的areaList格式必须时以上的。可以把后台的省放进province_list,市和区也相对应的放进相应的list。
官方提供的json数据很明显。是根据地区前的数字编码进行筛选的。编码为6位,前2位是对应市从11开始。中间2位对应的是市,从01开始。最后的2位编码是区,也是从01开始。
代码如下:
export const mixin1={
methods:{
async getAddress(){//vue mixin
let res=await this.$axios('/other/get-address-all');
let address={};
let province_list={};
let city_list={};
let county_list={};
let n1=110000;
if(res.data.level=='success'){//获取自主传入的地址
let arr=[]
res.data.data.forEach((val)=>{
if(val.name!=''){
province_list[n1]=val.name;
if(val.cityList!=''){
// debugger
let n2=110;
let city=val.cityList;
city.forEach(val=>{
city_list[n1+n2]=val.name;
if(val.areaList!=''){
let n3=10;
val.areaList.forEach(val=>{
let obj={};
county_list[n1+n2+n3]=val.name;
obj[val.name]=val.townList
n3+=10
arr.push(obj);
})
n2+=100
// this.$store.dispatch('setTownList',arr)//存入区对应的镇或街道
}
})
}
n1+=10000;
}
this.$store.dispatch('setTownList',arr)//存入区对应的镇或街道;
})
}
this.areaList.province_list=province_list;
this.areaList.city_list=city_list;
this.areaList.county_list=county_list;
}
}
}
这里的逻辑是这样的,province_list 对应n(n1=110000);areaList.city_list对应n (n2+n1=110+110000);
county_list对应的n是(n3+n2+n1=10+110+110000)
这里要注意的是,n+=*的放的位置,应该放在当层,并且当层遍历完才递增
此外。这2个三级联动,并不只局限与地址,也可用于其他的数据(这不是废话···,自己传进去的数据)
延申:4级联动
由于本人的智力有限,在一个组件内实现4级联动,脑力跟不上。遂用3+1的方法实现···
其实在移动端这样实现,也有好处,就是看起来3+1比4看起来更好看,不用挤在一起啊
工作地区为3级联动
街道为没有联动
实现思路是这样。
三级联动跟上边提到的一样。
当选中三级联动后,获取到三级联动的最后一项,如天河区。然后再从town中筛选出来。
town的格式为{‘天河区’:[‘东圃’,‘车陂’],‘番禺’:[‘市桥’,‘沙湾’]…}数据可以跟最上提到的后台数据一次获取,也可以另外接口,你喜欢就好。
好了大功告成!!!