官方picker
可以设置有效时间,有效时间外的禁止选择,但是无法隐藏,于是决定通过picker-view
和picker-view-column
来手写一个,效果如图:

需要注意的一些地方:
- 2月份,需要判断是平/闰年;
- 大小月,30或31天;
- 还有就是选择本年,控制显示月份,选择本月控制显示日。
组件 wxml
<slot bindtap="handlePicker">slot>
<view hidden="{{!visible}}" class="date-picker-cover" bindtap="tapCancel">view>
<view class="date-picker" animation="{{animationData}}">
<view class="btn-area">
<view class="btn-cancel" bindtap="tapCancel">取消view>
<view class="btn-confirm" bindtap="tapConfirm">确定view>
view>
<picker-view class="picker-view" value="{{value}}" bindchange="changeDate">
<picker-view-column>
<view wx:for="{{years}}" wx:key="index" class="picker-view-column">{{item}}年view>
picker-view-column>
<picker-view-column>
<view wx:for="{{showDate.months}}" wx:key="index" class="picker-view-column">{{item > 9 ? item : '0' + item}}月view>
picker-view-column>
<picker-view-column>
<view wx:for="{{showDate.days}}" wx:key="index" class="picker-view-column">{{item > 9 ? item : '0' + item}}日view>
picker-view-column>
picker-view>
view>
组件 js
Component({
properties: {
dateValue: {
type: String,
observer: function (val) {
if (val) {
this.initDate(val)
}
}
}
},
data: {
visible: false,
years: [],
curDate: {
year: null,
month: null,
day: null
},
fullDate: {
months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
days: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
},
showDate: {
months: [],
days: []
},
value: null,
dateArr: null,
formatDate: '',
animate: null,
animationData: null
},
pageLifetimes: {
show() {
let animate = wx.createAnimation({
duration: 400,
timingFunction: 'ease',
})
this.setData({
animate
})
}
},
methods: {
handlePicker() {
const slideUp = this.data.animate.bottom(0).step()
this.setData({
animationData: slideUp.export(),
value: this.data.value,
visible: true
})
},
initDate(val) {
const date = new Date()
const curDate = {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate()
}
let years = []
for (let i = 1; i <= curDate.year; i++) {
years.push(i)
}
const value = val.split('-')
this.setData({
years,
curDate,
value: value.map(item => Number(item) - 1)
})
this.computedDate(value)
},
changeDate(val) {
let value = val.detail.value.map(item => item + 1)
this.computedDate(value)
const month = value[1] > 9 ? value[1] : '0' + value[1]
const day = value[2] > 9 ? value[2] : '0' + value[2]
this.setData({
dateArr: val.detail.value,
formatDate: `${value[0]}-${month}-${day}`,
})
},
computedDate (val) {
const { months: fullMonths, days: fullDays } = this.data.fullDate
const year = Number(val[0])
const month = Number(val[1])
const leapYear = !(year % 4) && (year % 100) || !(year % 400) ? true : false
let monthType = null
if (month === 2) {
monthType = 0
} else if ([4, 6, 9, 11].includes(month)) {
monthType = 1
}
let months = year === this.data.curDate.year ? fullMonths.slice(0, this.data.curDate.month) : fullMonths
let days = fullDays
if (year === this.data.curDate.year && month === this.data.curDate.month) {
days = fullDays.slice(0, this.data.curDate.day)
} else {
if (monthType === 0) {
days = leapYear ? fullDays.slice(0, 29) : fullDays.slice(0, 28)
} else if (monthType === 1) {
days = fullDays.slice(0, 30)
}
}
this.setData({
['showDate.months']: months,
['showDate.days']: days
})
},
tapConfirm() {
const slideDown = this.data.animate.bottom('-560rpx').step()
this.triggerEvent('change', this.data.formatDate)
this.setData({
value: this.data.dateArr,
animationData: slideDown.export(),
visible: false
})
},
tapCancel() {
const slideDown = this.data.animate.bottom('-560rpx').step()
this.setData({
animationData: slideDown.export(),
visible: false
})
}
}
})
组件 wxss
.date-picker-cover {
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, .5);
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
.date-picker {
width: 100%;
position: absolute;
left: 0;
bottom: 0;
background-color: #fff;
position: fixed;
bottom: -560rpx;
left: 0;
z-index: 100;
}
.date-picker .btn-area {
box-sizing: border-box;
width: 100%;
display: flex;
justify-content: space-between;
padding: 18rpx 30rpx;
border-bottom: 2rpx solid #f6f6f6;
font-size: 32rpx;
}
.date-picker .btn-area .btn-cancel {
color: #7f7f7f;
}
.date-picker .btn-area .btn-confirm {
color: #07c160;
}
.date-picker .picker-view {
width: 100%;
height: 480rpx;
}
.date-picker .picker-view .picker-view-column {
line-height: 34px;
text-align: center;
font-size: 32rpx;
}
调用组件
<view>
<date-picker dateValue="{{date}}" bindchange="changeDate">
<view class="date-content">选择日期:{{date}}view>
date-picker>
view>
Page({
data: {
date: '2021-12-02'
},
onLoad() {
},
changeDate(val) {
this.setData({
date: val.detail
})
}
})
{
"usingComponents": {
"date-picker": "/components/date-picker/date-picker"
}
}