微信小程序中自定义组件的使用

  微信小程序没有select下拉框的标签,我们可以自己写一个component组件来实现下拉框的功能。


  先介绍下,微信小程序中组件的使用和传参。在微信小程序中要使用自己自定义的组件需要在组件的json文件中设置component=true.

  select.json:

{
  "component": true,
  "usingComponents": {}
}

  然后在需要调用组件的页面json文件中设置绑定调用组件的地址:

{
  "usingComponents": {
    "select":"../../components/select/select"
  }
}

  然后就可以在页面中使用组件的标签来直接使用组件了。


select组件

子页面代码示例:

  select.js:

Component({
  properties: {
    options: {
      type: Array,
      value: []
    },
    defaultOption: {
      type: Object,
      value: {
        id: '000',
        name: '下拉框'
      }
    },
    key: {
      type: String,
      value: 'id'
    },
    text: {
      type: String,
      value: 'name'
    }
  },
  data: {
    isShow: false,
    current: {}
  },
  methods: {
    optionTap(e) {
      let dataset = e.target.dataset
      console.log(dataset)
      this.setData({
        current: dataset,
        isShow: false
      });

      // 调用父组件方法,并传参
      this.triggerEvent("change", { ...dataset })
    },
    openClose() {
      this.setData({
        isShow: !this.data.isShow
      })
    },

    // 此方法供父组件调用
    close() {
      this.setData({
        isShow: false
      })
    }
  },

  lifetimes: {
    attached() {
      // 属性名称转换, 如果不是 { id: '', name:'' } 格式,则转为 { id: '', name:'' } 格式
      let result = []
      if (this.data.key !== 'id' || this.data.text !== 'name') {       
        for (let item of this.data.options) {
          let { [this.data.key]: id, [this.data.text]: name } = item
          result.push({ id, name })
        }
      }
      
      this.setData({
        current: Object.assign({}, this.data.defaultOption),
        result: result
      })
    }
  }
})

  

  select.wxml:

<view class="select-box">
  <view class="select-current" catchtap="openClose">
    <text class="current-name">{{current.name}}</text>
  </view>
  <view class="option-list" wx:if="{{isShow}}" catchtap="optionTap">
    <text class="option"
      data-id="{{defaultOption.id}}"
      data-name="{{defaultOption.name}}">全部
    </text>
    <text class="option"
      wx:for="{{result}}"
      wx:key="{{item.id}}"
      data-id="{{item.id}}"
      data-name="{{item.name}}">{{item.name}}
    </text>
  </view>
</view>

  

  select.wxss:

.select-box {
  position: relative;
  width: 100px;
  font-size: 30rpx;
}

.select-current {
  position: relative;
  width: 100%;
  padding: 0 10rpx;
  line-height: 70rpx;
  border: 1rpx solid #ddd;
  border-radius: 6rpx;
  box-sizing: border-box;
}

.select-current::after {
  position: absolute;
  display: block;
  right: 16rpx;
  top: 30rpx;
  content: '';
  width: 0;
  height: 0;
  border: 10rpx solid transparent;
  border-top: 10rpx solid #999;
}

.current-name {
  display: block;
  width: 85%;
  height: 100%;
  word-wrap: normal;
  overflow: hidden;
}

.option-list {
  position: absolute;
  left: 0;
  top: 76rpx;
  width: 100%;
  padding: 12rpx 20rpx 10rpx 20rpx;
  border-radius: 6rpx;
  box-sizing: border-box;
  z-index: 99;
  box-shadow: 0rpx 0rpx 1rpx 1rpx rgba(0, 0, 0, 0.2) inset;
  background-color: #fff;
}

.option {
  display: block;
  width: 100%;
  line-height: 70rpx;
  border-bottom: 1rpx solid #eee;
}

.option:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

  这样组件就写好了,组件是子页面,调用组件的页面是父页面。子页面和父页面之间相互传值的方式不同。

  父页面向子页面传值,通常在标签中赋值就可以,不过能传的值需要在子页面的js文件中的properties中先定义类型和默认value,见上方select.js代码块中的properities部分。

  子页面向父页面传值通常是定义一个方法,在方法中使用下述代码传值:

this.triggerEvent("change", {...dataset}) //第一个放方法名,父页面bind:change="(父页面自定义方法)"中关联引用。第二个是要传的数据名。


父页面代码示例:
  index.wxml:

<view class="selectList" bindtap="close">
  <view class="select-wrap">
    <select id="select" defaultOption="{{teach_type}}" options="{{teach_type_list}}" key="type_id" text="type_name"  bind:change="change_teach_type"></select>
  </view>
</view> 

  

  index.js:

var app=getApp()
Page({
  data: {

  //类型
  teach_type_target:"类型",
  teach_type:{
    id:"000",
    name:"类型"
  },
  teach_type_list:[
    {
      type_id:"001",
      type_name:"上门辅导"
    },
    {
      type_id:"002",
      type_name:"在线辅导"
    },
  ],


  change_teach_type(e){
    this.setData({
      teach_object_target:e.detail.name  //e为子页面传回的数据
    })
  }

  
})