微信小程序自定义多列选择器的使用

一,预览

微信小程序在自带的表单组件中加入了选择器picker,并给出了常用的时间和省市区三级联动选择器,但日常开发中不可能仅仅使用这些选择器,所以我们在学习时先写一个常见的自定义选择器,用于满足项目中的日常需要。
先给出效果图:(先声明选择器中数据为测试使用,与真实情况无关)
在这里插入图片描述

二,picker属性

一个简单地多列选择器只要给picker组件加属性mode="multiSelector"即可,绑定数据时使用range来绑定一个数组作为显示内容,下面是官方给出的属性解释。在这里插入图片描述

三,创建组件

我们可以先在.wxml建一个自定义picker组件:

<picker 
    mode="multiSelector" 
    bindchange="bindCustomPickerChange"   
    bindcolumnchange="bindCustomPickerColumnChange" 
    value="{
   
   {customIndex}}" 
    range="{
   
   {onlyArray}}"
    >
    <view>
      多列自创选择器:{
   
   {onlyArray[0][customIndex[0]]}},{
   
   {onlyArray[1][customIndex[1]]}},{
   
   {onlyArray[2][customIndex[2]]}}
    </view>
</picker>

要注意的是,此处的onlyArray数组只是当前显示内容的数组,并不是我们全部数据的数组。

四,自定义函数

写好组件,我们就来写js文件,思路如下:

1,先创建页面所需数据
Page({

  /**
   * 页面的初始数据
   */
  data: {
    //当前选中数组的下标值
    customIndex: [0, 0, 0],
    //当前选中数组
    onlyArray: [
      [],
      [],
      []
    ],
    //customArray假设为我们从后台获取到的json数据
    customArray: [{
        name: '百度',
        dept: [{
            name: '搜索',
            product: [{
                name: '百度搜索'
              },
              {
                name: '百度一下'
              },
            ]
          },
          {
            name: '团购',
            product: [{
              name: '百度糯米'
            }, {
              name: '饿了么'
            }]
          },
          {
            name: '音乐',
            product: [{
              name: '百度音乐'
            }]
          },
          {
            name: '问答社区',
            product: [{
              name: '百度贴吧'
            }]
          }
        ]
      },

      {
        name: '腾讯',
        dept: [{
            name: '社交',
            product: [{
                name: 'QQ'
              },
              {
                name: '微信'
              },
            ]
          },
          {
            name: '视频',
            product: [{
                name: '腾讯视频'
              },
              {
                name: '搜狐视频'
              },
            ]
          },

          {
            name: '短视频',
            product: [{
              name: '微视'
            }]
          }
        ]
      },
    ],
  },
2,加载页面时给出赋值函数。

可以看到,当前选中数组onlyArray是空的,在小程序显示时会直接显示成空,所以需要在页面创建时给一个初始值,这个初始值使用customIndex数组来给出,也可以用于页面数据回填。代码如下:

 /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    var data = {
      customArray: this.data.customArray,
      customIndex: this.data.customIndex,
      onlyArray: this.data.onlyArray,
    };
    for (var i = 0; i < data.customArray.length; i++) {
      data.onlyArray[0].push(data.customArray[i].name);
    }
    for (var j = 0; j < data.customArray[data.customIndex[0]].dept.length; j++) {
      data.onlyArray[1].push(data.customArray[data.customIndex[0]].dept[j].name);
    }
    for (var k = 0; k < data.customArray[data.customIndex[0]].dept[data.customIndex[1]].product.length; k++) {
      data.onlyArray[2].push(data.customArray[data.customIndex[0]].dept[data.customIndex[1]].product[k].name);
    }
    this.setData(data);
  },
3,创建组件监听函数。

这里需要两个函数,分别是bindchange(打开组件后点击确定触发)和bindcolumnchange(打开组件后滑动列触发)。

//多列自定义选择器改变value的方法
  bindCustomPickerChange: function(e) {
    var customArray = this.data.customArray,
      customIndex = this.data.customIndex,
      onlyArray = this.data.onlyArray;

    console.log('picker发送选择改变,携带值为', e.detail.value);
    //此处e.detail.value为当前选择的列的下标值数组,如[0,1,0]
    
    console.log('picker最终选择值为:', onlyArray[0][customIndex[0]], onlyArray[1][customIndex[1]], onlyArray[2][customIndex[2]]);
    this.setData({
      customIndex: e.detail.value
    })
  },

  //多列自创选择器换列方法
  bindCustomPickerColumnChange: function(e) {
    var customArray = this.data.customArray,
      customIndex = this.data.customIndex,
      onlyArray = this.data.onlyArray;

    customIndex[e.detail.column] = e.detail.value;
    // console.log(onlyArray);

    var searchColumn = () => {
      for (var i = 0; i < customArray.length; i++) {
        var arr1 = [];
        var arr2 = [];
        if (i == customIndex[0]) {
          for (var j = 0; j < customArray[i].dept.length; j++) {
            arr1.push(customArray[i].dept[j].name);
            if (j == customIndex[1]) {
              for (var k = 0; k < customArray[i].dept[j].product.length; k++) {
                arr2.push(customArray[i].dept[j].product[k].name);
              }
              onlyArray[2] = arr2;
            }
          }
          onlyArray[1] = arr1;
        }
      };
    }

    switch (e.detail.column) {
      case 0:
        customIndex[1] = 0;
        customIndex[2] = 0;
        searchColumn();
        break;
      case 1:
        customIndex[2] = 0;
        searchColumn();
        break;
    }
    this.setData({
      onlyArray: onlyArray,
      customIndex: customIndex
    });
  },
 

需要说明的是,

1)bindchange和bindcolumnchange两个函数都是eventhandle类型的,但他们绑定的数据不同。

  • bindchange函数的e.detail.value为当前选择的所有列的下标值数组,如[0,1,0]代表当前选择器的三列数据下标;

  • bindcolumnchange函数的e.detail.column代表当前选择的是第几列,e.detail.value为具体的当前选择的第几列的数据的下标,是一个数字。

2)在bindcolumnchange函数中,进行e.detail.column的判断,

  • 如果e.detail.column == 0,则代表改变的是第一列的数据,此时要将第二列和第三列的数据下标全部置为0,即置为缺省数据,并将onlyArray数组进行联动变化;

  • 如果e.detail.column ==1,则代表改变的是第二列的数据,此时将第三列的数据下标置为0,将onlyArray数组进行联动变化;

  • 如果e.detail.column ==2,则代表改变的是第三列的数据,而前两列不需要进行变化,故不需要判断这种情况的数组变化。

3)点击确定后,调用bindchange方法得到选择结果。我们可以得到的数据包括两部分,

  • 一是当前选择的所有列的下标值数组,即customIndex,数据回填时即使用这部分数据;
  • 二是当前选择的内容,我们用customIndex中的下标查找onlyArray数组中的具体内容得到具体值,例如 " 百度,搜索,百度一下 "。

五,遇到的问题

在这里遇到一个bug,如果在switch语句中将customIndex[0]或customIndex[1]置为0的语句放在searchColumn()后边时,数组显示会混乱,如图所示:
在这里插入图片描述
即第一列换列时,如果第二列数据下标非0,则第三列数据无法对应上。

根据上述bug描述,我猜想可能是在switch判断中将后列数据下标置为0的操作晚于数组变化的的方法才会导致此问题。

所以后来将customIndex[0]或customIndex[1]置为0的语句放在searchColumn()前才解决了此问题。

六,总结

此时我们的自定义多列选择器就建好了,使用json数据作为总数据,可以自定义选项,可以得到想要的两部分数据,可以数据回填,基本满足了项目中的实际需要。

猜你喜欢

转载自blog.csdn.net/yichensheng/article/details/91389145