小程序修改时间选择器组件
程序员文章站
2024-01-22 19:35:10
...
目的:
在实际开发中,小程序提供的picker时间选择器无法修改样式,这可能与项目整体的风格不一致,因此借助小程序picker-view实现自定义样式的时间选择器
功能:
支持默认时间,初始值是当天,根据选择的不同年月日限制可选值(因为大小月平年闰年天数不一样)
readme
Props
defaultValue:string(2019-10-15)
默认值:当前时间
Events
cancel:Function
说明:取消时触发
参数:null
confirm:Function
说明:确定时触发
参数:event.detail选中的时间
直接将下面代码复制即可直接使用
js
// components/date_time_picker/index.js
const years = []
const months = []
const days = []
const date = new Date
const currentYear = date.getFullYear()
const currentMonth = date.getMonth() + 1
const currentDay = date.getDate()
// 根据年和月获取当月天数
function getDayNum(year, month) {
return new Date(year, month, 0).getDate()
}
for (let i = currentYear; i <= 2099; i++) {
years.push(i)
}
for (let i = currentMonth; i <= 12; i++) {
months.push(i)
}
for (let i = currentDay; i <= getDayNum(currentYear, currentMonth); i++) {
days.push(i)
}
let selectedYear = currentYear
let selectedMonth = currentMonth
let selectedDay = currentDay
Component({
ready() {
let timeArr = this.data.defaultValue.split('-').map(i => Number(i))
selectedYear = timeArr[0]
selectedMonth = timeArr[1]
selectedDay = timeArr[2]
let months = []
let days = []
let monthStartFlag = 1
let monthEndFlag = 12
let dayStartFlag = 1
let datEndFlag = getDayNum(timeArr[0],timeArr[1])
if (timeArr[0] == currentYear) {
monthStartFlag = currentMonth
}
if (timeArr[0] == currentYear && timeArr[1] == currentMonth){
dayStartFlag = currentDay
}
for (let i = monthStartFlag; i <= monthEndFlag; i++) {
months.push(i)
}
for (let i = dayStartFlag; i <= datEndFlag; i++) {
days.push(i)
}
this.setData({
months,
days
})
let yearIndex = this.data.years.indexOf(timeArr[0])
let monthIndex = this.data.months.indexOf(timeArr[1])
let dayIndex = this.data.days.indexOf(timeArr[2])
this.setData({
yearDefaultIndex: yearIndex,
monthDefaultIndex: monthIndex,
dayDefaultIndex: dayIndex
})
},
properties: {
defaultValue: {
type: String,
value: `${currentYear}-${currentMonth}-${currentDay}`
}
},
data: {
years,
months,
days,
yearDefaultIndex: null,
monthDefaultIndex: null,
dayDefaultIndex: null
},
methods: {
pickerChange: function (ev) {
let _this = this
let index = ev.detail.value[0]
let type = ev.target.dataset.type
let typeMap = {
year: function (index) {
let year = _this.data.years[index]
console.log(year,'年')
selectedYear = year
// 设置月
let monthStartFlag = 1
let months = []
if (year == currentYear) {
monthStartFlag = currentMonth
let monthIndex = null
let dayIndex = null
if(selectedMonth <= currentMonth){
selectedMonth = currentMonth
monthIndex = 0
if(selectedDay < currentDay){
selectedDay = currentDay
dayIndex = 0
}else{
dayIndex = selectedDay - currentDay
}
}else{
monthIndex = selectedMonth - currentMonth
dayIndex = selectedDay - 1
}
_this.setData({
monthDefaultIndex: monthIndex,
dayDefaultIndex: dayIndex
})
} else {
setTimeout(() => {
_this.setData({
monthDefaultIndex: selectedMonth - 1,
dayDefaultIndex: selectedDay - 1
})
}, 0)
}
for (let i = monthStartFlag; i <= 12; i++) {
months.push(i)
}
_this.setData({
months
})
// 设置日
let dayStartFlag = 1
let days = []
let dayEndFlag = getDayNum(selectedYear, selectedMonth)
if (selectedYear == currentYear && selectedMonth == currentMonth) {
dayStartFlag = currentDay
}
for (let i = dayStartFlag; i <= dayEndFlag; i++) {
days.push(i)
}
_this.setData({
days
})
},
month: function (index) {
let month = _this.data.months[index]
console.log(month,'月')
selectedMonth = month
let dayStartFlag = 1
let days = []
let dayEndFlag = getDayNum(selectedYear, selectedMonth)
if (selectedYear == currentYear && selectedMonth == currentMonth) {
dayStartFlag = currentDay
selectedMonth = currentMonth
selectedDay = currentDay
_this.setData({
monthDefaultIndex: 0,
dayDefaultIndex: 0
})
} else {
let selectedDayIndex = selectedDay - 1
setTimeout(() => {
if (selectedDayIndex >= _this.data.days.length) { // 大月最后一天会大于小月
selectedDayIndex = _this.data.days.length - 1
}
_this.setData({
dayDefaultIndex: selectedDayIndex
})
}, 0)
}
for (let i = dayStartFlag; i <= dayEndFlag; i++) {
days.push(i)
}
_this.setData({
days
})
},
day: function (index) {
let day = _this.data.days[index]
console.log(day,'日')
selectedDay = day
}
}
typeMap[type](index)
},
cancelAction: function () {
this.triggerEvent('cancel')
},
confirmAction: function () {
let year = selectedYear
let month = selectedMonth
let day = selectedDay
if (month < 10) {
month = '0' + month
}
if (day < 10) {
day = '0' + day
}
this.triggerEvent('confirm', `${year}-${month}-${day}`)
}
}
})
wxml
<!--components/date_time_picker/index.wxml-->
<view class="picker-wrapper">
<view class="picker-toolbar">
<text class="cancel" catch:tap="cancelAction">取消</text>
<text class="confirm" catch:tap="confirmAction">确定</text>
</view>
<view class="picker-item-wrapper">
<picker-view value="{{[yearDefaultIndex]}}" class="picker-item-year" indicator-style="height: 40px;" bindchange="pickerChange" data-type="year">
<picker-view-column>
<view wx:for="{{years}}" wx:key="{{index}}" class="picker-item-value">{{item}}年</view>
</picker-view-column>
</picker-view>
<picker-view value="{{[monthDefaultIndex]}}" class="picker-item-month" indicator-style="height: 40px;" bindchange="pickerChange" data-type="month">
<picker-view-column>
<view wx:for="{{months}}" wx:key="{{index}}" class="picker-item-value">{{item}}月</view>
</picker-view-column>
</picker-view>
<picker-view value="{{[dayDefaultIndex]}}" class="picker-item-day" indicator-style="height: 40px;" bindchange="pickerChange" data-type="day">
<picker-view-column>
<view wx:for="{{days}}" wx:key="{{index}}" class="picker-item-value">{{item}}日</view>
</picker-view-column>
</picker-view>
</view>
</view>
/* components/date_time_picker/index.wxss */
@keyframes popupTitle {
from {
bottom: 0;
}
to {
bottom: 40%;
}
}
@keyframes popup {
from {
bottom: -40%;
}
to {
bottom: 0rpx;
}
}
.picker-wrapper {
z-index: 999;
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
}
.picker-wrapper .picker-toolbar {
background-color: white;
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 48px;
display: flex;
align-items: center;
font-size: 32rpx;
justify-content: space-between;
padding: 0 32rpx;
animation: popupTitle 0.4s normal forwards;
}
.picker-wrapper .picker-toolbar .confirm {
color: #006EFF;
}
.picker-wrapper .picker-item-wrapper {
display: flex;
background-color: white;
position: absolute;
right: 0;
bottom: -40%;
left: 0;
height: 40%;
animation: popup 0.4s normal forwards;
}
.picker-wrapper .picker-item-year,
.picker-item-month,
.picker-item-day {
flex: 1;
}
.picker-wrapper .picker-item-year,
.picker-item-month,
.picker-item-day .picker-item-value {
text-align: center;
line-height: 40px;
}