小程式:動態資料實現三級聯動選擇器

小心夾手發表於2018-03-09

每個週五的下午,坐在電腦邊,沏上一杯熱茶,按捺不住激動的心情,為了週末的休息不上班嗎?不,安靜的環境是為了能夠更好的學習!!!

image.png

便捷的picker

藉助picker元件可以很便捷的幫我們實現省市區、日期時間、多列選擇器,接下來我們來來實現一個動態資料的多列選擇器。

效果圖

先上效果圖

效果圖

互動

首先使用者點選選擇購車門店按鈕,選擇省級地區,然後通過選擇的省級key充當查詢條件獲取市級資料,然後用選擇市級後的key查詢門店資料。

image.png

資料結構

後端哥們給的資料結構都一樣,長這個樣子

資料結構

我們使用每條資料的value用來顯示,使用key 來進行請求,最後獲取到選擇的門店key,然後丟個後端哥們進行儲存即可。

wxml

來來來,跟著我的節奏,讓我看到你們的雙手,哎,沒讓你打節奏,是敲程式碼 ?️?️

<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}}" multiArray就是我們的多維陣列,這次我們用來放置資料所有的名字 4、value="{{multiIndex}}" multiIndex也是陣列,用來表示選擇的多維陣列的每一項的第幾個 5、bindchange是value改變觸發的事件,bindcolumnchange每一列值改變時候觸發的事件

如果你需要一個完美的解釋,請戳 ? 完整API

兩個小夥伴

bindcolumnchange

上面說了,bindcolumnchange用來繫結每一列值改變時候觸發的事件,他高大威猛

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改變觸發的事件,他很清秀

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、頁面載入後,呼叫獲取省級資料的函式,這個函式自己會去拿市級和門店的資料

以上若不明白,可以結合最後的程式碼去理解

完整程式碼

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、還沒想好,湊字數吧。

相關文章