关于小程序的自定义三级联动与vant组建的三级联动,以及四级联动

最近的项目要求是地址选择器是自定义的地址,不能直接用全国的地址。由于小程序提供的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的格式为{‘天河区’:[‘东圃’,‘车陂’],‘番禺’:[‘市桥’,‘沙湾’]…}数据可以跟最上提到的后台数据一次获取,也可以另外接口,你喜欢就好。
好了大功告成!!!

猜你喜欢

转载自blog.csdn.net/weixin_43743956/article/details/85031747