[小程序]动态数据实现picker多列选择器

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


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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容