天天看點

mpvue:用picker實作普通滾動選擇元件并向父元件傳回選中的值

首先看看全文要實作的效果圖:

mpvue:用picker實作普通滾動選擇元件并向父元件傳回選中的值

說明:在“釋出我的閑置物品”這個頁面裡,有一個所屬分類的選項,我選擇使用小程式原生的picker來做普通的滾動選擇。這裡,實作“釋出我的閑置物品”這個頁面的/src/pages/createGoods/index.vue作為父元件,另外封裝/src/components/selectBox.vue作為子元件來實作滾動選擇器。父元件将需要渲染的可選值(例如:電子産品、運動器材等)通過props傳遞給子元件。然後子元件将被選中的值通過$emit傳回給父元件。

在父元件中,首先擷取所有分類,得到資料形式如下:

mpvue:用picker實作普通滾動選擇元件并向父元件傳回選中的值

為了 不分散注意,以下展示的代碼隻貼出分類目錄相關部分,父元件/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  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  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
    }
}