阅读 3699

小程序:动态数据实现三级联动选择器

每个周五的下午,坐在电脑边,沏上一杯热茶,按捺不住激动的心情,为了周末的休息不上班吗?不,安静的环境是为了能够更好的学习!!!

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、还没想好,凑字数吧。

关注下面的标签,发现更多相似文章
评论