在開發(fā)中,小程序提供了內(nèi)置picker組件來供開發(fā)者使用。但picker組件無法自定義按鈕顏色、選擇器樣式,造成在有UI要求時束手無策(我覺得滑動體驗也不是很好orz)。這個時候就需要使用picker-view組件來自定義彈出滾動選擇器了。
樣式如下:
彈出樣式
首先確定組件的屬性
加入pickerShow是因為項目中有需要觸發(fā)選擇器彈出的需求
- picker-show 【Boolean】控制彈出隱藏
- range 【二維Array】 二維數(shù)組,長度表示多少列,數(shù)組的每項表示每列的數(shù)據(jù)
- title 【Array】 選擇器每列標(biāo)題
- value 【Array】 value 每一項的值表示選擇了 range 對應(yīng)項中的第幾個(下標(biāo)從 0 開始)
- is-shadow 【Boolean】 是否需要顯示遮罩層
- bindchange 【EventHandle】 value 改變時觸發(fā) change 事件 event.detail = value
- bindfinish 【EventHandle】 完成時觸發(fā) event.detail = value
- bindcancel 【EventHandle】 取消時觸發(fā)
需要有幾列,就在 range 中傳入幾項
// 使用時,可插入選擇器標(biāo)題
<my-picker range="{{val}}" title="{{['標(biāo)題1','標(biāo)題2']}}" bindfinish="finishHandler" is-shadow="{{true}}">
<text>從底部彈起的滾動選擇器</text>
</my-picker>
// 頁面邏輯
Page({
data: {
val: [// 數(shù)據(jù)列表
['大天狗', '玉藻前', '妖刀姬', '茨木童子'],
['追月神', '姑獲鳥', '犬神', '黑童子']
]
},
finishHandler(e){
console.log(e.detail)// 選擇的結(jié)果 如:["妖刀姬", "犬神"]
}
})
// .json
{
"usingComponents": {
"my-picker": "/components/my-picker/my-picker"
}
}
如有需要定制樣式,就可以直接在components組件中直接修改就可以啦~
下面是組件的完整代碼
// my-picker.js
Component({
/**
* 組件的屬性列表
*/
properties: {
pickerShow:{
type: Boolean, // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型)
value: false, // 屬性初始值(可選),如果未指定則會根據(jù)類型選擇一個
observer (newVal, oldVal, changedPath) {
// 屬性被改變時執(zhí)行的函數(shù)(可選),也可以寫成在methods段中定義的方法名字符串, 如:'_propertyChange'
// 通常 newVal 就是新設(shè)置的數(shù)據(jù), oldVal 是舊數(shù)據(jù)
}
},
isShadow: {
type: Boolean,
value: true,
observer(newVal, oldVal, changedPath) {}
},
range:{
type: Array,
value: []
},
title:{
type: Array,
value: []
},
value: {// picker-view 內(nèi)的 picker-view-column 當(dāng)前選擇的是第幾項
type: Array,
value: [2, 2]
}
},
/**
* 組件的方法列表
*/
methods: {
pickerHandler() {// 控制彈出層顯示隱藏
this.setData({ pickerShow: !this.data.pickerShow })
},
bindChange(e) {// value 改變時觸發(fā) change 事件
const val = e.detail.value
this.setData({ value: val })
let arr = []
this.data.range.forEach((v, i) => {
arr.push(v[this.data.value[i]])
})
this.triggerEvent('change', arr, {})
},
pickerFinish() {// 滾動選擇器 - 完成
let arr = []
this.data.range.forEach((v, i) => {
arr.push(v[this.data.value[i]])
})
this.pickerHandler()
this.triggerEvent('finish', arr, {})
},
pickerCancel() {// 滾動選擇器 - 取消
this.pickerHandler()
this.triggerEvent('cancel', arr, {})
}
}
})
// my-picker.wxml
<view>
<button bindtap='pickerHandler'>從底部彈起的滾動選擇器</button>
<view class='com-picker-view {{pickerShow}}'>
<view class='com-picker-title'>
<view class='com-picker-cancel' bindtap='pickerCancel'>取消</view>
<view class='com-picker-result'><slot></slot></view>
<view class='com-picker-finish' bindtap='pickerFinish'>完成</view>
</view>
<view class='com-title' wx:if="{{propTitle.length!=0}}">
<view wx:for="{{title}}" wx:key="{{index}}">{{item}}</view>
</view>
<picker-view indicator-style="height: 40px;" style="width: 100%; height: 200px;" value="{{value}}" bindchange="bindChange">
<picker-view-column wx:for="{{range}}" wx:key="{{index}}">
<view wx:for="{{item}}" wx:for-item="a" style="line-height: 40px">{{a}}</view>
</picker-view-column>
</picker-view>
</view>
<view class='com-picker-shadow {{pickerShow}}' bindtap='pickerHandler' wx:if="{{isShadow}}"></view>
</view>
/*my-picker.wxss*/
picker-view-column{font-size: 14px;text-align: center;}
.com-picker-view{position: fixed;bottom: 0;width: 100%;z-index: 3;background: #fff;}
/* 彈出標(biāo)題 */
.com-picker-title{display: flex;padding: 10px 15px;font-size: 14px;border-bottom: #f8f8f8 1px solid;}
.com-picker-cancel{color: #999;}
.com-picker-finish{color: palevioletred;}
.com-picker-result{flex: 1;text-align: center;color: #999;}
.com-title{display: flex;border-bottom: #f8f8f8 1px solid;}
.com-title > view{flex:1;text-align: center;line-height: 40px;font-size: 14px;}
/* 彈出效果 */
.com-picker-view.false{transform:translateY(100%);-webkit-transform:translateY(100%);transition: all .3s cubic-bezier(0,.54,.51,.99);-webikit-transition: all .3s cubic-bezier(0,.54,.51,.99);opacity: 1;}
.com-picker-view.true{transform:translateY(0%);-webkit-transform:translateY(0%);transition: all .3s cubic-bezier(0,.54,.51,.99);-webikit-transition: all .3s cubic-bezier(0,.54,.51,.99);opacity: 1;}
/* 遮罩 */
.com-picker-shadow{width: 100%;height: 100%;position: fixed;top: 0;left: 0; background-color:rgba(0,0,0,0.3);z-index: 2}
.com-picker-shadow.true{ -webkit-transition: opacity 0.35s, visibility 0.35s;transition: opacity 0.35s, visibility 0.35s;visibility: visible;opacity: 1;}
.com-picker-shadow.false{visibility: hidden;opacity: 0; -webkit-transition: opacity 0.35s, visibility 0.35s;transition: opacity 0.35s, visibility 0.35s;}
// my-picker.json
{
"component": true,
"usingComponents": {}
}