小程序中没有现成的下拉选择组件,有个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();
});
}
},
})
页面效果图: