实现微信小程序自定义select组件
在做小程序的时候发现小程序中不能像H5页面一样使用select标签,因此需要自行定义select组件来解决这个问题,如下是个人封装的自定义select组件,效果图在结尾,仅供参考,有不合理处可以指出
<!-- WXML -->
<view class="select">
<view class="sel_title">{{title}}</view> <!-- 绑定js中数据,用来显示select文字 -->
<view class="sel_Text" bind:tap="changeExpand"><!-- changeExpand控制展开关闭->图标切换等-->
<text>{{selName}}</text><!-- 绑定js中数据,用来显示选中的文字 -->
<icon class="iconfont {{isExpand?'icon-Up':'icon-Down'}}" /> <!-- 图标,可自定义 -->
</view>
<view class="select_list {{isExpand ? 'active' : ''}}" wx:if="{{select}}" > <!--下拉列表 -->
<scroll-view style="max-height: 600rpx;" scroll-y="true" show-scrollbar="false" enhanced="true">
<view class="select_item" wx:for="{{dataList}}" wx:key="keyProp" bindtap="SelectItem" data-value="{{item[keyProp]}}" data-name="{{item[valueProp]}}">{{item[valueProp]}}</view>
</scroll-view>
</view>
</view>

// WXS
Component({
/* 父组件传递的数据 */
properties: {
title: {
type: String,
value: ''
},
dataList: {
type: Array,
value: [
{ value: 1, name: '苹果'},
{ value: 2, name: '香蕉'},
{ value: 3, name: '橘子'},
{ value: 1, name: '苹果'},
{ value: 2, name: '香蕉'},
{ value: 3, name: '橘子'},
]
},
select: {
type: Boolean,
value: true
},
//以下俩属性可根据父组件传递过来的值绑定对应数据,可以任意数据的key-value字段,默认key为value字段,value为name字段
keyProp: {
type: String,
value: 'value'
},
valueProp: {
type: String,
value: 'name'
},
},
data: {
isExpand: false,
selName: '',
selValue: '',
currSelectItem: {},
Keys: [],
},
methods: {
changeExpand(){//下拉框展开/收缩
let isExpand = !this.data.isExpand
this.setData({
isExpand: isExpand,
})
},
SelectItem(e){//选择选项
const value = e.currentTarget.dataset.value
const name = e.currentTarget.dataset.name
//处理传进的数据,根据外部数据将key-value字处理成外部的字段
const currSelectItem = this.data.dataList.filter((v,i)=>{
return v[this.data.keyProp] == value && v[this.data.valueProp] == name
})
//存储选中的数据
this.setData({
selValue: value,
selName: name,
isExpand: false,
currSelectItem: currSelectItem[0]
})
//触发父组件中的事件,在父组件使用bindSelcallback=‘父组件中自定义事件’
this.triggerEvent('Selcallback',currSelectItem[0])
}
}
})
// WXSS 样式可以自己调整,图标需要自己引入,这里使用阿里的iconfont
@import '../../../styles/iconfont.wxss';
.select{
display: flex;
width: 100%;
height: 60rpx;
line-height: 60rpx;
/* justify-content: space-around; */
position: relative;
margin: 30rpx 0 0 0 ;
}
.sel_title {
width: 100rpx;
height: 60rpx;
background-color: #fff;
margin-right: 20rpx;
text-align: center;
}
.sel_Text {
width: 80%;
height: 60rpx;
box-sizing: border-box;
box-shadow: 1px 1px 8px 0 #ccc;
border-radius: 10rpx;
text-align: center;
font-size: 28rpx;
}
.sel_Text > .icon-Up,.icon-Down {
position: absolute;
width: 30px;
height: 30px;
right: 20rpx;
}
.select_list {
position: absolute;
display: none;
top: 60rpx;
right: 20rpx;
min-width: 220rpx;
max-width: 420rpx;
/* max-height: 400rpx; */
height: 0;
padding-top: 20rpx;
background-color: rgb(241, 241, 241);
box-sizing: border-box;
z-index: 888;
overflow: hidden;
border-bottom-left-radius: 20rpx;
border-bottom-right-radius: 20rpx;
border-top: none;
text-align: center;
}
.active {
display: block;
height: auto;
}
.select_item {
padding: 8rpx 20rpx;
font-size: 28rpx;
box-sizing: border-box;
}