快速实现一个自定义日期时间 picker
最近有个自定义时间选取功能需求,特此提取整理成代码片段,分享给可能有需要的小伙伴参考。
具体效果:
方式一:采用 [代码]picker[代码] 多列选择器。相关代码
方式二:采用[代码]picker-view[代码]自定义。相关代码
[图片]
[图片]
代码仓库:
https://git.weixin.qq.com/sg996/datetime-picker
分享链接:
https://developers.weixin.qq.com/s/YMM1Icmy7GDN
代码片段:
方式一:[代码]datetime-picker/index.js[代码]
[代码]const dayjs = require('../../utils/dayjs.min.js');
const HOUR_UNIT = '时';
const MINUTE_UNIT = '分';
const weekdaysShort = '周日_周一_周二_周三_周四_周五_周六'.split('_');
const getDateList = () => {
let list = []
// 获取未来三十天时间(实现来自百度参考)
for (var i = 0; i < 30; i++) {
let time = new Date(new Date()
.setDate(new Date().getDate() + i)).toLocaleDateString();
time = dayjs(time).format('YYYY/MM/DD'); // 兼容性差异处理
const temp = {
date: dayjs(time).format('YYYY/MM/DD'),
year: dayjs(time).format('YYYY'),
month: dayjs(time).format('MM'),
text: `${dayjs(time).format('MM月DD日')} ${weekdaysShort[dayjs(time).day()]}`
}
list.push(temp)
}
return list;
}
const getHourList = (isToday = true) => {
const hour = dayjs().hour();
const minute = dayjs().minute();
let list = []
if (isToday) {
list = [...new Array(24).keys()].filter(i => i >= +hour).map(i => (`00${i}`.substr(-2)));
if (minute > 45 && list.length > 1) list.shift();
} else {
list = [...new Array(24).keys()].map(i => (`00${i}`.substr(-2)));
}
list = list.map(i => ({
text: `${i}${HOUR_UNIT}`
}))
return list;
}
const getMinuteList = (isToday = true, isHour = true) => {
const minute = dayjs().minute();
let list = ['15', '30', '45'].filter(i => +i >= +minute).map(i => i);
if (!isToday || !isHour || minute > 45) list = ['00', '15', '30', '45'];
list = list.map(i => ({
text: `${i}${MINUTE_UNIT}`
}))
return list;
}
const defaultHourList = [...new Array(24).keys()].map(i => (`00${i}`.substr(-2))).map(i => ({
text: `${i}${HOUR_UNIT}`
}))
const defaultDateRange = [getDateList(), getHourList(), getMinuteList()]
Component({
properties: {
currentDate: {
type: String,
value: dayjs(),
},
},
data: {
timeIndex: [0, 0, 0],
dateRange: defaultDateRange,
oldDateRange: defaultDateRange,
},
observers: {
'currentDate': function (date) {
// 时间格式
if (isNaN(date) && !isNaN(Date.parse(date))) {
// 回显时间小于当前时间按当前时间
if (dayjs(date).isBefore(dayjs())) {
date = dayjs()
}
} else {
date = dayjs()
}
// 回显数据(先转换整点时刻)
let day = dayjs(date).format('YYYY/MM/DD')
let hour = dayjs(date).format('HH')
let minute = dayjs(date).format('mm')
if (+minute > 45) {
hour = (`00${+hour + 1}`.substr(-2));
minute = '00';
date = `${day} ${hour}:${minute}`;
}
if (+hour === 24) {
hour = '00';
date = dayjs(`${day} ${hour}:${minute}`).add(1, 'day').format('YYYY/MM/DD HH:mm');
day = dayjs(date).format('YYYY/MM/DD');
}
const isToday = dayjs().isSame(date, 'day')
const isHour = dayjs().isSame(date, 'hour')
const dateList = getDateList()
const dateHour = getHourList(isToday)
let dateMinute = getMinuteList(isToday, isHour)
let d0 = dateList.findIndex(i => i.date === day)
d0 = d0 === -1 ? 0 : d0;
let d1 = dateHour.findIndex(i => i.text === `${hour}${HOUR_UNIT}`)
d1 = d1 === -1 ? 0 : d1;
let d2 = dateMinute.findIndex(i => +minute <= +i.text.replace(MINUTE_UNIT, ''))
d2 = d2 === -1 ? 0 : d2;
// 更新对应数据
this.setData({
'dateRange[1]': dateHour,
'dateRange[2]': dateMinute,
timeIndex: [d0, d1, d2],
oldDateRange: [getDateList(), dateHour, dateMinute],
})
}
},
methods: {
bindMultiPickerColumnChange(e) {
const {
column,
value,
} = e.detail;
// 第一列【不是】第一个时,第二列默认固定数据
if (column === 0 && value !== 0) {
this.setData({
'dateRange[1]': defaultHourList,
})
}
// 第一列【是】第一个时,重置第二列
if (column === 0 && value === 0) {
this.setData({
'dateRange[1]': getHourList(),
})
}
// 当第一列 【或】 第二列【不是】第一个时,第三列默认固定数据
if ([0, 1].includes(column) && value !== 0) {
this.setData({
'dateRange[2]': ['00', '15', '30', '45'].map(i => ({
text: `${i}${MINUTE_UNIT}`
}))
})
}
// 当第一列 【和】 第二列【都是】第一个时,重置第三列
const timeIndex = e.currentTarget.dataset.value;
if (timeIndex[0] === 0 && timeIndex[1] === 0) {
this.setData({
'dateRange[2]': getMinuteList()
})
}
},
bindPickerChange(e) {
const timeIndex = e.detail.value;
const [c1, c2, c3] = timeIndex;
const dateRange = this.data.dateRange;
const [l1, l2, l3] = dateRange;
const hour = l2[c2].text.replace(HOUR_UNIT, '')
const minute = l3[c3].text.replace(MINUTE_UNIT, '')
const dateTime = `${l1[c1].date} ${hour}:${minute}`;
const dateTimeText = `${l1[c1].text} ${hour}${HOUR_UNIT}${minute}${MINUTE_UNIT}`;
this.setData({
timeIndex,
})
this.triggerEvent('confirm', {
dateTime,
dateTimeText
})
},
bindPickerCancel(e) {
const timeIndex = e.target.dataset.value;
const oldDateRange = this.data.oldDateRange;
this.setData({
timeIndex,
dateRange: oldDateRange,
})
}
}
})
[代码]
[代码]datetime-picker/index.wxml[代码]
[代码]<picker mode="multiSelector" bindcolumnchange="bindMultiPickerColumnChange" bindchange="bindPickerChange" bindcancel="bindPickerCancel" value="{{timeIndex}}" data-value="{{timeIndex}}" data-key="timeIndex" range="{{dateRange}}" range-key="text">
<slot />
</picker>
[代码]