1.首先在components 里面设置组件名称:van-select(随便取名字);
2.新建文件写代码:
wxml:
<view class="w100 select_all_view"><!-- 标题,可以没有 --><view class="mr-10 pt-10 size-28" style="width: {{titleWidth}};" wx:if="{{title}}">{{title}}</view><view class="select_view relative" style="width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};max-width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};"><view class="inputPlaceholder h100 w100 radius-10 relative flex_l pd-10 {{ disabled ? 'gray-3' : 'black' }}" bindtap="{{disabled || readonly ? '' : 'changeShow'}}" style="background: {{disabled ?'#f5f7fa' : bgColor}};border: 2rpx solid #ddd;"><block wx:if="{{disabled || readonly}}"><view class="flex-1" wx:if="{{selectLabel}}">{{selectLabel}}</view><view class="flex-1 gray-3 line-1" wx:else>{{placeholder}}</view><van-icon class="gray-3" name="arrow-down" /></block><block wx:else><block wx:if="{{selectLabel}}"><view class="flex-1">{{selectLabel}}</view><van-icon class="gray-3" name="clear" wx:if='{{!show}}' catchtap="clearInput" /><van-icon class="gray-3" name="arrow-up" wx:else /></block><block wx:else><view class="flex-1 gray-3 line-1">{{placeholder}}</view><van-icon class="gray-3" name="arrow-down" class="transfer {{show ? 'is-reverse' : 'no-reverse' }}" /></block></block></view><!-- 下拉展开后的可选择内容 --><block wx:if='{{show}}'><view class="{{toTop ? 'triangleBox-top' : 'triangleBox'}}"><view class="{{toTop ? 'triangle-top' : 'triangle'}}"></view></view><view class="content radius-10 pd-20 size-28" style="{{toTop ? 'top: -' + (options.length > 4 ? 150 : (options.length * 30 + 40)) + 'rpx; margin-top: -6rpx;' : 'margin-top: 10rpx;'}}"><view class="pd-10 center gray-3" wx:if="{{options.length < 1}}">暂无数据</view><view class="line-1 w100 pd-10 contentItem {{item[valueName] == selectValue ? 'bold':''}}" wx:for="{{options}}" wx:key="index" bindtap="handleChange" data-item="{{item}}" style="color: {{ item[valueName] == selectValue ? textColor : '#000'}}; background: {{item[valueName] == selectValue ? itemBgColor:''}};">{{item[labelName]}}</view></view></block></view>
</view>
wxss:
.select_all_view {display: flex;justify-content: start;align-items: start;z-index: 999;margin-bottom: 20rpx;
}.select_view {/* min-width: 200rpx; */min-height: 64rpx;
}.inputPlaceholder {font-size: 28rpx;
}
.flex_l{display: flex;
}
.flex-1{flex: 1;
}
.pd-10{padding:20rpx;
}
.relative{position: relative;
}
.radius-10{border-radius: 10rpx;
}
.icon {position: absolute;right: 12rpx;top: 20rpx;
}.contentItem {height: 30rpx;line-height: 30rpx;font-size: 24rpx;
}.content {width: calc(100% - 4px);margin-left: 2px;position: absolute;z-index: 999;max-height: 150rpx;background: #FFFFFF;/* border: 1px solid #ccc; */box-shadow: 0 0 4px #ccc;opacity: 1;/* margin-top: 10rpx; */overflow-x: hidden;overflow-y: scroll;
}.triangleBox {position: absolute;z-index: 1000;left: 30rpx;
}.triangle {position: relative;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-bottom: 10rpx solid #ccc;
}.triangle::after {content: '';position: absolute;top: 3rpx;left: -12rpx;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-bottom: 10rpx solid #fff;
}.triangleBox-top {position: absolute;z-index: 1000;left: 30rpx;/* display: none; */
}.triangle-top {position: relative;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-top: 10rpx solid #ccc;
}.triangle-top::after {content: '';position: absolute;bottom: 3rpx;left: -12rpx;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-top: 10rpx solid #fff;
}.is-reverse {transform: rotate(180deg);
}.transfer {transition: transform .3s;
}.no-reverse {transition: rotate(0deg);
}
js:
Component({options: {addGlobalClass: true,},properties: {/* --------- 样式参数 --------- */titleWidth: { // 标题长度type: String,value: "60px"},bgColor: { // 输入框背景颜色type: String,value: "#fff"},itemBgColor: { // 选中的选项背景颜色type: String,value: "#F5F8FE"},textColor: { // 选中的字体颜色type: String,value: "#FF5733"},/* --------- 数据参数 --------- */title: { // 下拉框标题type: String,value: ""},number: { // 下拉框标题type: String,value: ""},options: { // 选项数组type: Array,value: [],},labelName: { // 选项数组-绑定的label名称type: String,value: "dictLabel",},valueName: { // 选项数组-绑定的value名称type: String,value: "dictValue"},modelValue: { // 绑定的valuetype: String,value: "",observer: function () {//如果有默认值,需要匹配出name,所以这里使用obersver,当父组件中值改变时触发this.handleData();}},placeholder: { // 输入框为空时占位符type: String,value: "请选择"},disabled: { // 是否禁用type: Boolean,value: false},readonly: { // 是否只读type: Boolean,value: false}},/*** 页面的初始数据*/data: {show: false, //选项框及图标展示selectValue: "", //选中的valueselectLabel: "", //选中的labeltoTop: false, // 下拉框是否展示在输入框上方},attached() {this.handleData()},methods: {// 清空输入框clearInput() {this.setData({selectValue: "", //选中的valueselectLabel: "", //选中的labelshow: false,})},// 下拉框收起和展开changeShow(e) {let that = thisconst query = wx.createSelectorQuery();// 选择当前点击的 view 元素query.select('.inputPlaceholder'+this.data.number).boundingClientRect();query.exec(function (res) { // res[0].bottom 是元素距离可视区域顶部的距离加上元素自身的高度; res[1].scrollTop 是页面的滚动距离var show = !that.data.showif (res[0]) {/* that.triggerEvent("handleShow", show); // [暂未发现]处理滚动选项区域时背景页面滚动问题 */let toBottom = wx.getSystemInfoSync().windowHeight - res[0].bottom;console.log('距离设备底部的距离:', toBottom);that.setData({toTop: toBottom < 150 ? true : false,show: show})} else {that.setData({ show: show })}});},// 选择数据后回显handleChange(e) {let { item } = e.currentTarget.datasetlet { labelName, valueName } = this.datathis.setData({selectValue: item[valueName],selectLabel: item[labelName],show: false})let obj = {}obj[valueName] = item[valueName]obj[labelName] = item[labelName]this.triggerEvent("handleChange", obj);// 传参},// 匹配值并回显handleData() {let { modelValue, options, valueName, labelName } = this.properties;if (modelValue) {let item = options.find(r => r[valueName] == modelValue)this.setData({selectLabel: item ? item[labelName] : modelValue,selectValue: modelValue,});}}}
})
json:
{"component": true,"usingComponents": {}
}
以上就是组件的全部代码,当然你也可以自己再按照需求改造,接下来就是组件的应用:
组件应用:
1.在所需要用组件的页面中引入组件,在所需页面的json中:
{"navigationBarTitleText": "","usingComponents": {"wan-select": "../components/van-select/index"}
}
2.在wxml里面使用:
<view class="cont-box"><wan-select
class="inputPlaceholder1"
options="{{options1}}"
number="1"
labelName="text"
valueName="id"
modelValue="{{selectedId1}}"
placeholder="请选择"
bindhandleChange="handleChange"
title=""
readonly="{{false}}"
disabled="{{options1.length == 0}}"></wan-select>
</view>
说明:
class="inputPlaceholder1" (自己写的类,可以修改样式)
options="{{options1}}"(下拉框的选项数据)
labelName="text"(选项数组-绑定的label名称)
valueName="id"(选项数组-绑定的value名称)
number="1"(自定义的值,多个select 有关联的情况下,添加,根据自己需求,一个的话没必要)
modelValue="{{selectedId1}}"(为了回显下拉框数据中选中的项)
bindhandleChange="handleChange"(操作事件)
title="" (下拉框左侧添加名称)
readonly="{{false}}"(是否只读)
disabled="“(是否禁用)
如图所示: