1. 程式人生 > >關於小程式的自定義三級聯動與vant組建的三級聯動,以及四級聯動

關於小程式的自定義三級聯動與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的格式為{‘天河區’:[‘東圃’,‘車陂’],‘番禺’:[‘市橋’,‘沙灣’]…}資料可以跟最上提到的後臺資料一次獲取,也可以另外介面,你喜歡就好。
好了大功告成!!!