评论

自定义下拉选择组件Select

下拉选择组件Select

背景

项目需求要实现类似html标签 <Select/>效果,所以写了一个类似效果的自定义组件。

效果图

wxml

<view class="view-item">
  <text class='item-key'>{{title}}<text style="color:red" wx:if="{{isRequired}}">*</text></text>
  <view class="view-select-container">
    <view class='select-value' bindtap="selectToggle">
      <input value="{{value}}" name='{{name}}' disabled="{{true}}" />
      <image class='img-arrow' style="width:40rpx;height:40rpx" src='/images/drop_down.png' />
    </view>
    <view class="view-options" wx:if="{{showOptions}}">
      <cover-view class='option-item' wx:for="{{options}}" data-index="{{index}}" bindtap="selectItem">{{item[showkey]}}</cover-view>
    </view>
    <view class="view-out" wx:if="{{showOptions}}" bindtap="hideSelect"></view>
  </view>
</view>

js

Component({
  behaviors: ['wx://form-field'], //支持表单获取组件值
  properties: {
    //组件的名称
    title: {
      type: String
    },
    //通过form获取组件的值
    name: {
      type: String
    },
    //下拉显示的数据集合
    options: {
      type: Array
    },
    //表单组件是否必填
    isRequired: {
      type: Boolean
    },
    //外部传递的动态变量
    showkey: {
      type: String
    }
  },
  data: {
    showOptions: false //组件默认的展开状态
  },
  /**
   * 组件的方法列表
   */
  lifetimes: {
    attached: function() {
      let key = this.properties.showkey
      this.setData({
        value: this.properties.options[0][key] //默认选中第一个
      })
    },
  },
  methods: {
    selectToggle: function(e) {
      this.setData({
        showOptions: !this.data.showOptions
      })
    },
    hideSelect: function(e) {
      this.setData({
        showOptions: false
      })
    },
    selectItem: function(e) {
      let optionList = this.properties.options //外部传进来的数组对象
      let nowIdx = e.currentTarget.dataset.index //当前点击的索引
      let selectItem = optionList[nowIdx] //当前点击的内容
      this.setData({
        showOptions: false,
        value: selectItem[this.properties.showkey]
      });
      let eventOption = {} // 触发事件的选项
      this.triggerEvent("mySelectItem", selectItem) //组件选中回调
    }
  }
})

wxss

.view-item {
  display: flex;
  align-items: center;
  padding: 2% 0%;
  /* border-bottom: 1px solid #eee; */
}

.item-key {
  font-size: 31rpx;
  color: #666;
  width: 25%;
}

.view-select-container {
  width: 75%;
  height: 80rpx;
  position: relative;
}

.select-value {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-sizing: border-box;
  border: 1px solid #eee;
  font-size: 31rpx;
  position: relative;
}

.img-arrow {
  width: 28rpx;
  height: 26rpx;
  padding-right: 10rpx;
}

.view-options {
  background-color: #fff;
  display: flex;
  width: 100%;
  z-index: 3;
  position: absolute;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.view-out {
  position: fixed;
  z-index: 2;
  width: 100%;
  left: 0;
  top: 0;
  height: 100%;
}

.option-item {
  font-size: 28rpx;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: -1px;
  text-align: center;
  box-sizing: border-box;
  border: 1px solid #eee;
  line-height: 80rpx;
  height: 80rpx;
}

input {
  padding-left: 3%;
  font-size: 30rpx;
}


使用

json中引入自定义组件

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

js

Page({
  data: {
    optionArry: [{
      "name": "香蕉",
      "id": "1"
    }, {
      "name": "苹果",
      "id": "2"
    }, {
      "name": "橘子",
      "id": "3"
    }, {
      "name": "雪梨",
      "id": "4"
    }],
  },
  onLoad: function() {},
})

wxml中使用

<Select title="类别" options="{{optionArry}}" isRequired="true" bind:mySelectItem='onSelectItem' name='formkey' showkey='name' />

总结:可以动态传递对象数组在组件中显示的属性名,类似picker的range-key;使用cover-view解决当组件展开时遮住原生组件时的点击击穿问题。

最后代码片段以供学习和参考:
https://developers.weixin.qq.com/s/RwZLwImG7kcE

最后一次编辑于  2019-11-08  
点赞 8
收藏
评论

10 个评论

  • Bailyn
    Bailyn
    2020-02-13

    这个有多选吗

    2020-02-13
    赞同 2
    回复
  • Alpha
    Alpha
    2023-03-19

    微信居然还没有select组件,难以置信。。。

    2023-03-19
    赞同 1
    回复
  • 。
    2019-11-07

    点击组件外部 收缩选项做了吗


    2019-11-07
    赞同 1
    回复 5
    • xt
      xt
      2019-11-07
      代码片段已经支持了 最新代码没贴上来
      2019-11-07
      回复
    • 。
      2019-11-08回复xt
      你这种实现方式我还是第一次见 一个页面里多个select会有问题的 而且每个组件都搞个view-out会影响全局的
      2019-11-08
      回复
    • xt
      xt
      2019-11-08回复
      我这边试了多个select使用没问题的哦 你具体遇到什么问题?实现方式的话我觉得没什么标准 容易理解没问题就ok 你可以说说你觉得最好的实现方式 供大家参考和学习!
      2019-11-08
      回复
    • 。
      2019-11-08回复xt
      第一个展开状态 直接点第二个 第二个不会展开 需要点2次
      2019-11-08
      回复
    • xt
      xt
      2019-11-08回复
      这个问题是有的 点击另一个是先隐藏的之前的 对使用的话影响不大 如果你觉得不能满足你的需求可以再此基础上优化和拓展
      2019-11-08
      回复
  • ma
    ma
    09-13

    菩萨

    09-13
    赞同
    回复
  • 再次寻找周杰伦
    再次寻找周杰伦
    2023-10-23

    多选有吗


    2023-10-23
    赞同
    回复
  • ...
    ...
    2023-09-15

    给你磕一个


    2023-09-15
    赞同
    回复
  • For |、Tomorrow
    For |、Tomorrow
    2020-03-31

    问下,怎么实现多选

    2020-03-31
    赞同
    回复
  • night suns
    night suns
    2019-11-25

    哦哦,我试试

    2019-11-25
    赞同
    回复
  • night suns
    night suns
    2019-11-25

    下面有textarea下拉选就有点问题

    2019-11-25
    赞同
    回复 1
    • xt
      xt
      2019-11-25
      你显示的时候用view 点击的时候再换成textarea
      2019-11-25
      回复
  • 九歌^
    九歌^
    2019-11-01

    捧场

    2019-11-01
    赞同
    回复 1
    • xt
      xt
      2019-11-01
      幸会幸会!握手
      2019-11-01
      回复
登录 后发表内容