2023 年 06 月 20 日原创
0
微信小程序 DatetimePicker 组件
先创建小程序组件目录,在通过开发者工具可直接生成组件套件,这里采用的是 TS+Scss 模板。
生成目录后
| components
| - datetime-picker
| -- datetime-picker.json
| -- datetime-picker.scss
| -- datetime-picker.ts
| -- datetime-picker.wxml
picker 开发里面用到了小程序开放的几个标签组件 (page-container, picker-view, picker-view-column) 和插槽 ( slot ),以下是文件源代码,没有注释:
<!-- datetime-picker.wxml -->
<view class="picker-component">
<view class="picker-trigger" bindtap="handleUsePicker">
<slot></slot>
</view>
<page-container show="{{ show }}" round>
<view class="picker-container">
<view class="picker-header">日期时间选择器</view>
<view class="picker-body">
<picker-view indicator-style="height: 50px;" class="picker-view" value="{{ selection }}" bindchange="handleUpdatePickerValue">
<picker-view-column>
<view wx:for="{{ years }}" wx:key="years" class="picker-column-item">{{ item }}</view>
</picker-view-column>
<picker-view-column>
<view wx:for="{{ months }}" wx:key="months" class="picker-column-item">{{ item }}</view>
</picker-view-column>
<picker-view-column>
<view wx:for="{{ dates }}" wx:key="dates" class="picker-column-item">{{ item }}</view>
</picker-view-column>
<picker-view-column>
<view wx:for="{{ hours }}" wx:key="hours" class="picker-column-item">{{ item }}</view>
</picker-view-column>
<picker-view-column>
<view wx:for="{{ minutes }}" wx:key="minutes" class="picker-column-item">{{ item }}</view>
</picker-view-column>
<picker-view-column wx:if="{{ second }}">
<view wx:for="{{ seconds }}" wx:key="seconds" class="picker-column-item">{{ item }}</view>
</picker-view-column>
</picker-view>
</view>
<view class="picker-footer">
<button bindtap="handleCancel">取消</button>
<button type="primary" bindtap="handleConfirm">确认</button>
</view>
</view>
</page-container>
</view>
// datetime-picker.ts
interface DateTimePickerOptions {
show: Boolean,
years: Array<number | string>,
months: Array<number | string>,
dates: Array<number | string>,
hours: Array<number | string>,
minutes: Array<number | string>,
seconds: Array<number | string>,
selection: Array<number>
}
const _n = (n: number) => n >= 10 ? n : `0${n}`
/**
* 获取指定长度的年份,已当前年份为中间值
* @param offsetLength 年份上下偏差
* @returns 年份数组
*/
function getYears (type: 'picker' | 'normal', offsetLength: number = 20) {
let _years = []
let currentYear = new Date().getFullYear()
for (let i = (type === 'picker' ? currentYear - offsetLength : currentYear); i < currentYear + offsetLength; i++) {
_years.push(i)
}
return _years
}
/**
* 根据传入的年月获取日期数量
* @param year 年份
* @param month 月份
* @returns 月份拥有的日期
*/
function getDates (year?: number, month?: number) {
year = year || new Date().getFullYear()
month = month || new Date().getMonth() + 1
let monthMaxDateLength = new Date(year, month, 0).getDate()
let dates = []
for (let i = 1; i <= monthMaxDateLength; i++) {
dates.push(_n(i))
}
return dates
}
function getNumberArray (length: number = 12) {
let nums = []
for (let i = 1; i <= length; i++) {
nums.push(_n(i))
}
return nums
}
Component({
/**
* 组件的属性列表
*/
properties: {
value: String,
second: Boolean,
normal: Boolean
},
/**
* 组件的初始数据
*/
data: <DateTimePickerOptions>{},
lifetimes: {
ready () {
this.init()
}
},
/**
* 组件的方法列表
*/
methods: {
init () {
let options: DateTimePickerOptions = {
show: false,
years: getYears(this.data.normal ? 'normal' : 'picker'),
months: getNumberArray(),
dates: getDates(),
hours: getNumberArray(24),
minutes: getNumberArray(60),
seconds: getNumberArray(60),
selection: []
}
if (!this.data.value) {
let _d = new Date()
options.selection = [
options.years.indexOf(_d.getFullYear()),
options.months.indexOf(_n(_d.getMonth() + 1)),
options.dates.indexOf(_n(_d.getDate())),
options.hours.indexOf(_n(_d.getHours())),
options.minutes.indexOf(_n(_d.getMinutes())),
options.seconds.indexOf(_n(_d.getSeconds()))
]
}
this.setData(options)
this.setData({
selection: options.selection
})
},
handleUsePicker () {
this.setData({ show: true })
},
handleUpdatePickerValue (e: any) {
this.setData({ selection: e.detail.value })
},
handleCancel () {
this.setData({ show: false })
},
handleConfirm () {
let value = [
this.data.years[this.data.selection[0]],
this.data.months[this.data.selection[1]],
this.data.dates[this.data.selection[2]],
this.data.hours[this.data.selection[3]],
this.data.minutes[this.data.selection[4]]
]
if (this.data.second) {
value.push(this.data.seconds[this.data.selection[5]])
}
let format = [
[value[0], value[1], value[2]].join('/'),
[value[3], value[4], this.data.second ? value[5] : ''].join(':')
].join(' ')
this.triggerEvent('confirm', {
value,
format
})
this.setData({
show: false
})
}
}
})
// datetime-picker.scss
.picker-container {
padding-bottom: env(safe-area-inset-bottom);
}
.picker-header {
text-align: center;
padding: 32rpx;
}
.picker-body {
height: 40vh;
.picker-view {
height: 100%;
.picker-column-item {
height: 50px;
text-align: center;
}
}
}
.picker-footer {
display: flex;
padding: 20rpx 32rpx 0;
button {
margin: 0 16rpx;
padding: 24rpx 0;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
}