小程序中没有现成的下拉选择组件,有个picker组件,但是是底部弹出的,不满足我的需求,所以重新封装了一个。
封装的下拉组件
html部分:
<view class="select_all_view"><!-- 内容说明,可以没有 --><view class="select_title" wx:if="{{title}}">{{title}}</view><view class="select_view" style="width: {{selectWidth}};"><!-- 输入框 --><view class="inputPlaceholder" bindtap="startChange"><text class="text" wx:if='{{select}}'>{{select}}</text><text class="text placeholder_text" wx:else="{{select}}">{{placeholder}}</text><view class="drop_down" wx:if='{{changable}}'><image style="width:48rpx;height:48rpx" src="../../image/drop_up.png" mode="" /></view><view class="drop_down" wx:else='{{changable}}'><image style="width:48rpx;height:48rpx" src="../../image/drop_down2.png" mode="" /></view></view><!-- 下拉展开后的可选择内容 --><view class="content" wx:if='{{changable}}'><view class="select_item {{item.id==selectId ? 'active':''}}" wx:for="{{selectcontent}}" wx:key="idnex" bindtap="changecontent" data-datavalue="{{item}}">{{item.name}}</view></view></view>
</view>
css部分:
.select_all_view {display: flex;z-index: 999;
}.select_view {display: inline;position: relative;
}.inputPlaceholder {width: 100%;height: 64rpx;border: 2rpx solid #3A3A3A;font-size: 28rpx;line-height: 32rpx;color: #D8D4D4;border-radius: 12rpx;padding-left: 30rpx;box-sizing: border-box;position: relative;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}.select_view .inputPlaceholder .text {line-height:64rpx;
}.placeholder_text {color: #9B9B9B;font-size: 28rpx;
}.drop_down {position: absolute;right: 12rpx;top: 8rpx;
}.content {width: 100%;background: #FFFFFF;color: #505050;font-size: 30rpx;box-shadow: 0 0 12rpx 2rpx rgba(0, 0, 0, 0.38);border-radius: 16rpx;padding: 10rpx 12rpx;box-sizing: border-box;position: absolute;top: 76rpx;z-index: 999;
}.select_item {width: 100%;height: 76rpx;display: flex;justify-content: center;align-items: center;
}.select_view .content .active {background: #EDF5FF;border-radius: 4rpx;color: #1061FE;
}
js部分:
Component({properties: {selectWidth: {type: String,value: '100%'},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", { item: e.currentTarget.dataset.datavalue });//向父组件传参},//处理数据,复制一遍,因为子组件不能直接改变父组件的传进来的值。processData() {this.setData({selectcontent: this.properties.nameList,select: this.properties.nowName,selectId: this.properties.nowId,});},// 关闭下拉框closeSelect() {this.setData({changable: false});}}
})
在父组件中使用:
HTML部分:
<view class="dropdown_box"><dropdown style="margin-right: 20rpx;" class="dropdown" id="dropdown1" selectWidth="240rpx" nowId="{{firstTitleId}}" nameList="{{firstTitle}}" placeholder="请选择" nowName="{{firstTitleVal}}" bind:handleChange="changeFirstTitle"></dropdown><dropdown class="dropdown" id="dropdown2" selectWidth="240rpx" nowId="{{secondTitleId}}" nameList="{{secondTitle}}" nowName="{{secondTitleVal}}" placeholder="请选择" bind:handleChange="changeSecondTitle"></dropdown><dropdown class="dropdown" id="dropdown3" nowId="{{wordLimitId}}" nameList="{{wordLimitList}}" nowName="{{wordLimitVal}}" placeholder="请选择字数" bind:handleChange="changeWords"></dropdown>
</view>
.json文件:
{"usingComponents": {"dropdown":"../component/dropdown/dropdown"}
}
js部分:
Page({/*** 页面的初始数据*/data: {firstTitle: [{id: 1,name: '标题创作'},{id: 2,name: '社媒文案'},{id: 3,name: '故事创作'},],secondTitle: [], //二级标题数组wordLimitList: [{id: 1,name: '不限',value: 800},{id: 2,name: '约150字≈30s',value: 150},{id: 3,name: '约300字≈60s',value: 300},{id: 4,name: '约600字≈120s',value: 600},],firstTitleVal: "社媒文案",firstTitleId: 2,secondTitleVal: "文章改写",secondTitleId: 4,wordLimitVal: "",wordLimitId: 1},/*** 生命周期函数--监听页面加载*/onLoad(options) {},// 选择一级标题changeFirstTitle(e) {let selectId = e.detail.item.id},// 选择二级标题changeSecondTitle(e) {console.log(e)},// 选择字数changeWords(e) {},//点击当前选择框时,关闭其他下拉弹出框;点击页面其他部分,关闭所有下拉弹出框handlePageTap(e) {const dropdownIds = ['dropdown1', 'dropdown2', 'dropdown3'];const clickedId = e.target.id;if (dropdownIds.includes(clickedId)) {const otherDropdownIds = dropdownIds.filter(id => id !== clickedId);otherDropdownIds.forEach(id => {const dropdown = this.selectComponent('#' + id);dropdown.closeSelect();});} else {const dropdowns = this.selectAllComponents('.dropdown');dropdowns.forEach(dropdown => {dropdown.closeSelect();});}},
})
页面效果图: