一、起因
? ? ? ? 接到的項(xiàng)目需求,查看ui設(shè)計(jì)圖后,由于微信小程序官方設(shè)計(jì)的下拉選擇框不符合需求,而且常用的第三方庫也沒有封裝類似的,所以選擇自己自定義組件。在此記錄一下,方便日后復(fù)用。
? ? ? ? ui設(shè)計(jì)圖如下:
? ? ? ??
? ? ? ? 微信官方提供的選擇框
? ? ? ? 對(duì)比發(fā)現(xiàn)并不能實(shí)現(xiàn)我們想要的功能。
二、自定義組件?
2.1 封裝品牌組件
注:我這里的箭頭是使用Vant-Weapp生成的,可自由替換組件或圖片實(shí)現(xiàn),把相應(yīng)的wxss改掉即可
代碼如下
- wxml
<view class="select_all_view">
<!-- 內(nèi)容說明,可以沒有 -->
<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>
<!-- 下拉展開后的可選擇內(nèi)容 -->
<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;
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;
}
.select_view .content .active {
width: 184rpx;
height: 64rpx;
background: #F9F9F9;
border-radius: 0rpx 0rpx 0rpx 0rpx;
opacity: 1;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
line-height: 33rpx;
display: flex;
justify-content: center;
align-items: center;
}
.select_view .content .normal {
width: 184rpx;
height: 64rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
opacity: 1;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
line-height: 33rpx;
display: flex;
justify-content: center;
align-items: center;
}
- 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(){
//有的時(shí)候選項(xiàng)組是后端獲取數(shù)據(jù)來的,初始化時(shí)可能為[],所以這里使用obersver,當(dāng)父組件中值改變時(shí)觸發(fā)
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: ""
}
},
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
selectcontent: [],
changable: false, //箭頭切換
select: undefined, //選中的值
selectId: undefined, //選中的id
},
methods: {
// 下拉框收起和展開
startChange(e) {
this.setData({
changable: !this.data.changable
})
},
// 選擇數(shù)據(jù)后回顯
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});//向父組件傳參
},
//處理數(shù)據(jù),復(fù)制一遍,因?yàn)樽咏M件不能直接改變父組件的傳進(jìn)來的值。
processData(){
let options = [];
let that = this;
this.properties.nameList.forEach((item) => {
options.push({
id: item.id,
name: item.name,
});
}); //forEach
this.setData({
selectcontent: options,
select: that.properties.nowName,
selectId: that.properties.nowId,
});
}
}
})
2.2 組件調(diào)用與ui原型圖對(duì)比
? ? ? ? 在要使用組件的頁面js中添加自己想要的數(shù)據(jù)
- js
data: {
curfId: 1,
brandList: [{name: "萬達(dá)影視" ,id: 1},
{name: "金逸影視" ,id: 2},
{name: "CGV" ,id: 3}
],
curBrandName:"萬達(dá)影視" ,
}
- wxml?
<select-postSale nowId="{{curfId}}" nameList="{{brandList}}" nowName="{{curBrandName}}" placeholder="請(qǐng)選擇品牌" bind:handleChange="changeBrand"></select-postSale>
- json
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"select-postSale":"/components/select-postSale/select-postSale"
},
"navigationStyle": "custom"
? ? ui設(shè)計(jì)圖與效果對(duì)比
? ? ? ? 可以看到效果已經(jīng)基本實(shí)現(xiàn).具體細(xì)節(jié)需要優(yōu)化一下
2.3 封裝下方灰色區(qū)域組件
? ? ? ? 這個(gè)組件有兩個(gè)地方使用,樣式基本相同,拿上方的品牌組件修改一下樣式即可
代碼如下
- wxml
<!--pages/components/my_select/my_select.wxml-->
<view class="select_all_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>
<!-- 下拉展開后的可選擇內(nèi)容 -->
<view class="content" wx:if='{{changable}}'>
<view class="{{item.id==selectId ? 'active':'normal'}}" 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;
width: 654rpx;
height: 104rpx;
background: #F9F9F9;
border-radius: 12rpx 12rpx 12rpx 12rpx;
opacity: 1;
}
.select_view {
display: inline;
/* width: 200rpx;
height: 64rpx; */
}
.inputPlaceholder {
min-width: 654rpx;
height: 82rpx;
background: #F9F9F9;
border: 2rpx solid #D9D9D9;
border-radius: 12rpx 12rpx 12rpx 12rpx;
padding: 4rpx 0rpx 10rpx 10rpx;
/* color: #252525;
font-weight: 400; */
border-radius: 10rpx;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 32rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 38rpx;
}
.select_view .inputPlaceholder .text {
height: 40rpx;
position: relative;
top: 30rpx;
left: 24rpx;
}
.icon {
position: absolute;
right: 24rpx;
top: 30rpx;
}
.content {
position: absolute;
z-index: 999;
min-width: 626rpx;
max-height: 516rpx;
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 {
width: 638rpx;
height: 100rpx;
background: #F9F9F9;
font-size: 32rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 38rpx;
display: flex;
justify-content: center;
align-items: center;
}
.select_view .normal {
width: 638rpx;
height: 100rpx;
border-radius: 16rpx 16rpx 16rpx 16rpx;
opacity: 1;
font-size: 32rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 38rpx;
display: flex;
justify-content: center;
align-items: center;
}
- 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(){ //有的時(shí)候選項(xiàng)組是后端獲取數(shù)據(jù)來的,初始化時(shí)可能為[],所以這里使用obersver,當(dāng)父組件中值改變時(shí)觸發(fā) 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: "" } }, /** * 頁面的初始數(shù)據(jù) */ data: { selectcontent: [], changable: false, //箭頭切換 select: undefined, //選中的值 selectId: undefined, //選中的id }, methods: { // 下拉框收起和展開 startChange(e) { this.setData({ changable: !this.data.changable }) }, // 選擇數(shù)據(jù)后回顯 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});//向父組件傳參 }, //處理數(shù)據(jù),復(fù)制一遍,因?yàn)樽咏M件不能直接改變父組件的傳進(jìn)來的值。 processData(){ let options = []; let that = this; this.properties.nameList.forEach((item) => { options.push({ id: item.id, name: item.name, }); }); //forEach this.setData({ selectcontent: options, select: that.properties.nowName, selectId: that.properties.nowId, }); } } })
2.4 第二個(gè)組件調(diào)用與ui原型圖對(duì)比?
? ? ? ? 跟上方調(diào)用組件一樣.在使用組件頁面js中添加數(shù)據(jù),這里調(diào)用兩次組件即可,只是展示數(shù)據(jù)不一樣
- js
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
curfId: 1,
filmList: [{name: "堅(jiān)如磐石" ,id: 1},
{name: "變形金剛3" ,id: 2},
{name: "復(fù)仇者聯(lián)盟5" ,id: 3}
],
curFilmName: "復(fù)仇者聯(lián)盟5",
dateList: [{name: "2023/10/16" ,id: 1},
{name: "2023/10/23" ,id: 2},
{name: "2023/10/30" ,id: 3}
],
curDateName: "2023/10/16",
},
- wxml
<select-postSale_2 nowId="{{curfId}}" nameList="{{filmList}}" nowName="{{curFilmName}}" placeholder="請(qǐng)選擇要更換的電影"></select-postSale_2>
<select-postSale_2 nowId="{{curfId}}" nameList="{{dateList}}" nowName="{{curDateName}}" placeholder="請(qǐng)選擇要修改的日期"></select-postSale_2>
- json?
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"select-postSale_2":"/components/select-postSale_2/select-postSale_2"
},
"navigationStyle": "custom"
? ? ? ? ui原型圖與實(shí)現(xiàn)效果對(duì)比
電影部分
日期部分
三、自定義修改說明?
- 選擇框的大小修改inputPlaceholder樣式即可
舉個(gè)栗子: 此處我修改了寬度與背景色
.inputPlaceholder {
? min-width: 400rpx;//修改后的寬度
? height: 82rpx;
? background: #FF00FF; // 修改后的背景色
? border: 2rpx solid #D9D9D9;
? border-radius: 12rpx 12rpx 12rpx 12rpx;
? padding: 4rpx 0rpx 10rpx 10rpx;
? position: relative;
? overflow: hidden;
? text-overflow: ellipsis;
? white-space: nowrap;
? font-size: 32rpx;
? font-family: PingFang SC-Regular, PingFang SC;
? font-weight: 400;
? color: #000000;
? line-height: 38rpx;
}
- 選擇后的彈窗修改content樣式即可?
- 選中樣式修改active,沒選中樣式修改normal,彈窗大小修改content
舉個(gè)栗子:此處修改選中的背景色與沒選中的背景色(懶人,修改背景色容易區(qū)分)
- active
.select_view?.active?{
??width:?638rpx;
??height:?100rpx;
??background:?#32CD32;? // 修改后背景色
??font-size:?32rpx;
??font-family:?PingFang?SC-Regular,?PingFang?SC;
??font-weight:?400;
??color:?#000000;
??line-height:?38rpx;
??display:?flex;
??justify-content:?center;
??align-items:?center;
}
- normal
.select_view?.normal?{
??width:?638rpx;
??height:?100rpx;
??background: #FF6347;? // 修改后背景色
??opacity:?1;
??font-size:?32rpx;
??font-family:?PingFang?SC-Regular,?PingFang?SC;
??font-weight:?400;
??color:?#000000;
??line-height:?38rpx;
??display:?flex;
??justify-content:?center;
??align-items:?center;
}
其他的需要自定義的依照自己ui樣式修改即可。?文章來源:http://www.zghlxwxcb.cn/news/detail-752245.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-752245.html
到了這里,關(guān)于微信小程序--下拉選擇框組件封裝,可CV直接使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!