mpvue:用picker实现普通滚动选择组件并向父组件返回选中的值

首先看看全文要实现的效果图:

说明:在“发布我的闲置物品”这个页面里,有一个所属分类的选项,我选择使用小程序原生的picker来做普通的滚动选择。这里,实现“发布我的闲置物品”这个页面的/src/pages/createGoods/index.vue作为父组件,另外封装/src/components/selectBox.vue作为子组件来实现滚动选择器。父组件将需要渲染的可选值(例如:电子产品、运动器材等)通过props传递给子组件。然后子组件将被选中的值通过$emit返回给父组件。

在父组件中,首先获取所有分类,得到数据形式如下:

为了 不分散注意,以下展示的代码只贴出分类目录相关部分,父组件/src/pages/createGoods/index.vue代码如下:

<template>
  <div class="wrapper">
    <div class="properties">
      <div>
        <span class="mark"> * </span>
        <label class="title">所属分类:</label>
        <selectBox @selectedValue="updateBelongsCategory" :selectList="categoryList" ></selectBox>
      </div>
    </div>
  </div>
</template>

<script>
import selectBox from '@/components/selectBox'
export default {
  data () {
    return {
      categoryList: [],
      belongsCategory: 0
    }
  },
  components: {
    selectBox
  },
  methods: {
    //  接收子组件传值,获取选中的分类ID
    updateBelongsCategory (val) {
      this.belongsCategory = val
    },
    //  获取所有分类
    async initCategoryData () {
      await this.$http.get({
        'url': '/category/all'
      }).then(res => {
        //    使用nextTick同步视图更新
        this.$nextTick(() => {
          //    为了让子组件更加通用,这里将category_id更换为code,在子组件中将通过code来获取分类id
          let arr = JSON.parse(JSON.stringify(res).replace(/category_id/g, 'code'))
          this.categoryList = arr
        })
      })
    }
  },
  onLoad () {
    this.initCategoryData()
  }
}
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
.wrapper
  .properties
    font-size: 34rpx
    &>div
      padding: 20rpx 0
      display: flex
      line-height: 150%
      &>input
        width: 100%
        border: 1rpx solid #f4f4f4
        text-align: center
        padding: 10rpx 0
    .mark
      color: red;
      margin-right: 10rpx;
    .title
      white-space: nowrap
</style>

在父组件中传递给子组件的数据是object array类型的,我们在滚动选择器中要显示的名称就是该对象数组中每个对象的name属性,选中后我们应该将被选中对象的code属性值回传给父组件。根据微信开放文档,可以使用mode=selector,range来表示选择器的数据域,当range是个object array类型的时候,可以通过range-key来指定object中key的值作为显示内容。子组件/src/components/selectBox.vue代码如下:

<template>
  <div class="select_box">
    <picker mode="selector" :value="selectList[index].code" :range="selectList" range-key='name' @change="pickerChange">
      <view class="picker">
        {{selectList[index].name}}
      </view>
    </picker>
  </div>
</template>

<script>
export default {
  props: {
    'selectList': {
      type: Array
    }
  },
  data () {
    return {
      index: 0//  数组下角标
    }
  },
  methods: {
    //  改变选项
    pickerChange (e) {
      let value = e.mp.detail.value
      this.index = value
      //  发布自定义事件向父组件使传递数据
      this.$emit('selectedValue', this.selectList[value].code)
    }
  }
}
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
.select_box
  width: 100%
  text-align: center
  border: 1rpx solid #f4f4f4
</style>

对上述代码作说明:

在子组件/src/components/selectBox.vue中,接收父组件传递过来的对象数组类型数据:selectList,在picker标签中通过range指定selectList的值提供用户选择,range-key指定selectList数组中每个对象的name属性值作为显示内容。用index记录被选中对象在数组中的下角标,index初始值为0。value值为被选中对象的code属性值

    <picker mode="selector" :value="selectList[index].code" :range="selectList" range-key='name' @change="pickerChange">
      <view class="picker">
        {{selectList[index].name}}
      </view>
    </picker>

当value值发生变化时,会触发change事件。也就是用户选择完毕时会触发change绑定的事件pickerChange()。在pickerChange()方法中,e.mp.detail.value代表当前被选中对象在数组中的下角标。通过下角标可以获取当前被选中对象的code属性值。再通过$emit(event,arg)方法,绑定自定义event事件:selectedValue事件,并将code值作为参数传递给父组件。

methods: {
    //  改变选项
    pickerChange (e) {
      let value = e.mp.detail.value
      this.index = value
      //  发布自定义事件向父组件使传递数据
      this.$emit('selectedValue', this.selectList[value].code)
    }
  }

父组件通过在使用子组件时,@event(即@selectedValue="父组件方法")即可获取到子组件传递过来的值。

//    父组件中使用子组件时,监听了自定义事件:selectedValue事件
<selectBox @selectedValue="updateBelongsCategory" :selectList="categoryList" ></selectBox>


//    父组件方法updateBelongsCategory
methods: {
    //  接收子组件传值,获取选中的分类ID
    updateBelongsCategory (val) {
      this.belongsCategory = val
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章