美文网首页
微信小程序自定义 picker 多列选择器

微信小程序自定义 picker 多列选择器

作者: 夏海峰 | 来源:发表于2020-08-28 12:00 被阅读0次
    效果演示

    需求说明:使用 mpvue 实现自定义的 picker 多列选择器。

    1、数据结构说明

    根据 picker 的数据特征,需要构造一个如下所示的数据结构。data数组中的三个元素,分别用于渲染 picker 多列选择器的三列数据。能否构造出这个数据结构,直接影响了 picker 多列选择器实现的难易程度。

    pid的作用是用于构建出满足 picker 多列选择器的树状数据结构,要特别注意。

    const data = [
      // 用于picker第一列的数据源
      [
        {id:1, name:'A'},
        {id:2, name: 'B'}
      ],
      // 用于picker第二列的数据源
      [
        {id: 11, pid: 1, name: 'A1' },
        {id: 12, pid: 1, name: 'A2' },
        {id: 13, pid: 2, name: 'B1' },
        {id: 14, pid: 2, name: 'B2' },
        {id: 15, pid: 2, name: 'B3' }
      ],
      // 用于picker第三列的数据源
      [
        {id: 101, pid: 11, name: 'A1-0000000' },
        {id: 102, pid: 11, name: 'A1-1111111' },
        {id: 103, pid: 12, name: 'A2-0000000' },
        {id: 104, pid: 13, name: 'B1-0000000' },
        {id: 105, pid: 14, name: 'B2-0000000' },
        {id: 106, pid: 15, name: 'B3-0000000' },
      ]
    ]
    

    2、视图代码说明

    • picker 是微信小程序内置组件,基础使用方法请参见其官方文档。
    • mode 属性指定了 picker 是多列选择模式。
    • change 方法监听 picker 发生变化,用于最终获取 picker 的选择结果。
    • columnchange 方法监听 picker 列的变化,这个方法非常重要,在后面写 js 逻辑时要重点使用到它,因为列的变化会导致 picker 视图数据的变化。
    • range 是用于 picker 渲染的动态数据,其语法格式是 [[第一列数据], [第二列数据], [第三列数据]],在我们这个需求中,除了第一列数据是不变的之外,第二列和第三列数据都会随着父级数据的变化而变化。
    • range-key 用于指定使用哪个字段来渲染 picker 视图。
    <template>
      <picker
        mode="multiSelector"
        @change="change"
        @columnchange="columnChange"
        :value="idx"
        :range="list"
        range-key='name'
      >
        <view class="picker">
          <text>你选择的结果是:</text>
          <text v-text='list[0][idx[0]].name'></text>
          <text>、</text>
          <text v-text='list[1][idx[1]].name'></text>
          <text>、</text>
          <text v-text='list[2][idx[2]].name'></text>
        </view>
      </picker>
    </template>
    

    3、业务逻辑说明

    • 声明式变量idx,它是一个数组[第一列数据的索引, 第二列数据的索引, 第三列数据的索引],是多列选择器选择结果的索引号列表。
    • 声明式变量list,它是动态变化的,它用于渲染picker视图,每当columnchange列变化时,list都要发生变化,以保证 picker 多列的联动变化。注意和数据源data区分开来。
    • 此 demo 的核心难点是updatelist(col, idx)方法的封装,它负责修改list(注意灵活使用 filter 这个数组方法),进而更新 picker 视图的联动变化。
    • picker 视图变化分为三种情况:当第一列发生变化时,第二列和第三列都要变化;当第二列变化时,只影响第三列的变化;当第三列变化时,无须修改list
    export default {
      data: function() {
        return {
          idx: [0,0,0],  // 多列选择结果的索引号列表
          list: []       // 用于渲染UI
        }
      },
      onShow() {
        this.updatelist(0,0)  // 初始化渲染
      },
      methods: {
        // 确定picker选择结果时
        change(e) {
          let idx = e.target.value
          let arr = this.list
          this.idx = idx
          console.log('你选择的结果是:', arr[0][idx[0]].name, arr[1][idx[1]].name, arr[2][idx[2]].name)
        },
        // picker的列发生变化时
        columnChange(e) {
          // column列索引(0-第一列)  value是列中数组索引
          this.updatelist(parseInt(e.target.column), parseInt(e.target.value))
        },
    
        // 用于更新picker视图的方法封装
        updatelist(col, idx) {
          let list = this.list  // 视图渲染
          list[0] = data[0]      // picker的第一列数据
          // 当第一列变化时
          if(col==0) {
            // 更新第二列的数据
            list[1] = data[1].filter(ele=>ele.pid==list[0][idx].id)
            // 更新第三列的数据
            list[2] = data[2].filter(ele=>ele.pid==list[1][0].id)
            this.idx = [idx,0,0]
          }
          // 当第二列变化时
          if(col==1) {
            // 只用更新第三列数据
            list[2] = data[2].filter(ele=>ele.pid==list[1][idx].id)
            this.idx = [this.idx[0], idx, 0]
          }
          // 当第三列变化时,不用考虑
    
          // 更新list,更新picker视图
          this.list = list
        }
      }
    }
    

    本篇结束!!!

    相关文章

      网友评论

          本文标题:微信小程序自定义 picker 多列选择器

          本文链接:https://www.haomeiwen.com/subject/qrtlsktx.html