一、起因
接到的项目需求,查看ui设计图后,由于微信小程序官方设计的下拉选择框不符合需求,而且常用的第三方库也没有封装类似的,所以选择自己自定义组件。在此记录一下,方便日后复用。
ui设计图如下:
微信官方提供的选择框
对比发现并不能实现我们想要的功能。
二、自定义组件
2.1 封装品牌组件
代码如下
- wxml
<view class="select_all_view"><!-- 内容说明,可以没有 --><view class="select_title" wx:if="{{title}}">{{title}}</view><view class="select_view"><!-- 输入框 --><view class="inputPlaceholder" bindtap="startChange"><text class="text" wx:if='{{select}}' >{{select}}</text><text class="text" wx:else="{{select}}" >{{placeholder}}</text><view class="icon" wx:if='{{changable}}'><van-icon name="arrow-down" /></view><view class="icon" wx:else='{{changable}}'><van-icon name="arrow" /></view></view><!-- 下拉展开后的可选择内容 --><view class="content" wx:if='{{changable}}'><view class="{{item.id==selectId ? 'active':''}}" wx:for="{{selectcontent}}" wx:key="idnex" bindtap="changecontent" data-datavalue="{{item}}">{{item.name}}</view></view></view>
</view>
- wxss
/* components/select-postSale.wxss */
.select_all_view{display: flex;z-index: 999;}.select_view{display: inline;width: 200rpx;height: 64rpx;}.select_title{margin-right: 10rpx;}.inputPlaceholder{min-width: 230rpx;height: 64rpx;background: #FFFFFF;border: 2rpx solid #D9D9D9;border-radius: 12rpx 12rpx 12rpx 12rpx;padding: 4rpx 0rpx 10rpx 10rpx;border-radius: 10rpx;position: relative;overflow:hidden;text-overflow: ellipsis;white-space:nowrap;font-size: 28rpx;font-family: PingFang SC-Regular, PingFang SC;font-weight: 400;color: #000000;line-height: 33rpx;}.select_view .inputPlaceholder .text{height: 40rpx;position: relative;top: 16rpx;left: 12rpx;}.icon{position: absolute;right: 12rpx;top: 20rpx;}.content{position: absolute;z-index: 999;min-width: 200rpx;max-height: 208rpx;background: #FFFFFF;box-shadow: 0rpx 12rpx 32rpx 0rpx rgba(0,0,0,0.08), 0rpx 6rpx 12rpx -8rpx rgba(0,0,0,0.12), 0rpx 18rpx 56rpx 16rpx rgba(0,0,0,0.05);border-radius: 16rpx 16rpx 16rpx 16rpx;opacity: 1;margin-top: 8rpx;padding: 20rpx;overflow-x: hidden;overflow-y: scroll;display: flex;flex-direction: column;justify-content: center;align-items: center;}.content>.inputPlaceholder{padding: 10rpx 0;}.select_view .active{color:#46678d;}
- json
{"component": true,"usingComponents": {"van-icon": "@vant/weapp/icon/index"}
}
- js
// components/select-postSale.js
Component({properties: {title:{type: String,value: ""},nameList: {type: Array,value: [],observer: function(){//有的时候选项组是后端获取数据来的,初始化时可能为[],所以这里使用obersver,当父组件中值改变时触发this.processData();}},nowId: {type: Number,value: -1},nowName: {type: String,value: "",observer: function(){this.setData({select: this. properties.nowName,selectId: this.properties.nowId,});}},placeholder: {type: String,value: ""}},/*** 页面的初始数据*/data: {selectcontent: [],changable: false, //箭头切换select: undefined, //选中的值selectId: undefined, //选中的id},methods: {// 下拉框收起和展开startChange(e) {this.setData({changable: !this.data.changable})},// 选择数据后回显changecontent(e) {this.setData({select: e.currentTarget.dataset.datavalue.name,selectId: e.currentTarget.dataset.datavalue.id,changable: false})this.triggerEvent("handleChange", {selectId: this.data.selectId, select: this.data.select});//向父组件传参},//处理数据,复制一遍,因为子组件不能直接改变父组件的传进来的值。processData(){let options = [];let that = this;this.properties.nameList.forEach((item) => {options.push({id: item.id,name: item.name,});}); //forEachthis.setData({selectcontent: options,select: that.properties.nowName,selectId: that.properties.nowId,});}}})
2.2 组件调用
在要使用组件的页面js中添加自己想要的数据
- js
data: {curfId: 1,brandList: [{name: "万达影视" ,id: 1},{name: "金逸影视" ,id: 2},{name: "CGV" ,id: 3}],curBrandName:"万达影视" ,
}
- wxml
<select-postSale nowId="{{curfId}}" nameList="{{brandList}}" nowName="{{curBrandName}}" placeholder="请选择品牌" bind:handleChange="changeBrand"></select-postSale>
ui设计图与效果对比
可以看到效果已经基本实现.具体细节需要优化一下