微信小程序日期时间选择器以及组件封装

前言:

微信小程序摒除了select,因为觉得这个在移动端的操作以及显示不友好,从而产生了picker,picker也就是从底部弹起的滚动选择器,现在支持的有5种,通过mode来区分。但是呢这5种并没有包括日期时间选择权(日期和时间同时存在于picker的选择器)。因此完这里自定义了一个日期时间选择器。

多列选择器:mode = multiSelector

这里我们自定义选择器呢会用到多列选择器,它的api地址:这里

image

这里直接放代码吧

HTML
1
2
3
4
5
6
7
8
9
<view class="tui-picker-content">
<view class="tui-picker-name">日期时间选择器</view>
<picker mode="multiSelector" value="{{dateTime}}" bindchange="changeDateTime" bindcolumnchange="changeDateTimeColumn1"
range="{{dateTimeArray}}">
<view class="tui-picker-detail">
选择日期时间: {{dateTimeArray[0][dateTime[0]]}}-{{dateTimeArray[1][dateTime[1]]}}-{{dateTimeArray[2][dateTime[2]]}} {{dateTimeArray[3][dateTime[3]]}}:{{dateTimeArray[4][dateTime[4]]}}
</view>
</picker>
</view>
JavaScript
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
32
33
34
35
36
37
38
var dateTimePicker = require('../../utils/dateTimePicker.js');

Page({
data: {
date: '2018-10-01',
time: '12:00',
dateTimeArray: null,
dateTime: null,
startYear: 2000,
endYear: 2050
},
onLoad(){
// 获取完整的年月日 时分秒,以及默认显示的数组
var obj1 = dateTimePicker.dateTimePicker(this.data.startYear, this.data.endYear);
// 精确到分的处理,将数组的秒去掉
var lastArray = obj1.dateTimeArray.pop();
var lastTime = obj1.dateTime.pop();

this.setData({
dateTimeArray: obj1.dateTimeArray,
dateTime: obj1.dateTime
});
},
changeDateTime(e) {
this.setData({ dateTime: e.detail.value });
},
changeDateTimeColumn(e) {
var arr = this.data.dateTime, dateArr = this.data.dateTimeArray;

arr[e.detail.column] = e.detail.value;
dateArr[2] = dateTimePicker.getMonthDay(dateArr[0][arr[0]], dateArr[1][arr[1]]);

this.setData({
dateTimeArray: dateArr,
dateTime: arr
});
}
})
封装的组件dateTimePicker.js
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
function withData(param) {
return param < 10 ? '0' + param : '' + param;
}
function getLoopArray(start, end) {
var start = start || 0;
var end = end || 1;
var array = [];
for (var i = start; i <= end; i++) {
array.push(withData(i));
}
return array;
}
function getMonthDay(year, month) {
var flag = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0), array = null;

switch (month) {
case '01':
case '03':
case '05':
case '07':
case '08':
case '10':
case '12':
array = getLoopArray(1, 31)
break;
case '04':
case '06':
case '09':
case '11':
array = getLoopArray(1, 30)
break;
case '02':
array = flag ? getLoopArray(1, 29) : getLoopArray(1, 28)
break;
default:
array = '月份格式不正确,请重新输入!'
}
return array;
}
function getNewDateArry() {
// 当前时间的处理
var newDate = new Date();
var year = withData(newDate.getFullYear()),
mont = withData(newDate.getMonth() + 1),
date = withData(newDate.getDate()),
hour = withData(newDate.getHours()),
minu = withData(newDate.getMinutes()),
seco = withData(newDate.getSeconds());

return [year, mont, date, hour, minu, seco];
}
function dateTimePicker(startYear, endYear, date) {
// 返回默认显示的数组和联动数组的声明
var dateTime = [], dateTimeArray = [[], [], [], [], [], []];
var start = startYear || 1978;
var end = endYear || 2100;
// 默认开始显示数据
var defaultDate = date ? [...date.split(' ')[0].split('-'), ...date.split(' ')[1].split(':')] : getNewDateArry();
// 处理联动列表数据
/*年月日 时分秒*/
dateTimeArray[0] = getLoopArray(start, end);
dateTimeArray[1] = getLoopArray(1, 12);
dateTimeArray[2] = getMonthDay(defaultDate[0], defaultDate[1]);
dateTimeArray[3] = getLoopArray(0, 23);
dateTimeArray[4] = getLoopArray(0, 59);
dateTimeArray[5] = getLoopArray(0, 59);

dateTimeArray.forEach((current, index) => {
dateTime.push(current.indexOf(defaultDate[index]));
});

return {
dateTimeArray: dateTimeArray,
dateTime: dateTime
}
}
module.exports = {
dateTimePicker: dateTimePicker,
getMonthDay: getMonthDay
}

这里直接拿去用就完事了, 重点讲讲无比坑人的组件封装

组件封装

由于许多地方都需要用到日期时间选择器,因此为了代码的简(zhuang)洁(bi),我准备把它封装成一个组件,小程序自定义组件有点坑呐,反正官方看不到,我随便说hhh。这里picker是组件,index是需要使用组件的界面

构建目录

首先先创建一个目录为了存放公用组件

image

Component构造器

组件的构造跟普通的界面可不一样,它没有普通界面的生命周期(onLoad,onShow之类的),他的定义段和示例方法可以看这里

先奉上部分代码

picker
1
2
3
4
5
6
7
8
9
10
11
12
13
var dateTimePicker = require('../../utils/dateTimePicker.js');

Component({
data: {

},
ready() {

},
methods: {

}
})

这里我只用了众多定义段的其中三条,其他的自己去api里边

  1. data:组件的内部数据,和 properties 一同用于组件的模版渲染
  2. ready:组件生命周期函数,在组件布局完成后执行,此时可以获取节点信息(注意这里不是onLoad)
  3. methods:组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 组件事件

我在methods里面放着日期时间选择器的changeDateTime、changeDateTimeColumn方法,在ready里边放着上边onLoad里面的代码(自己去上边看哈)

自定义组件

我们要在自定义组件里面picker.json文件添加以下参数,意思是“我是组件”

picker
1
2
3
{
"component": true
}

使用组件

首先要在使用的地方的json文件添加以下参数

index
1
2
3
4
5
{
"usingComponents": {
"my-picker": "/components/picker/picker"
}
}

这样的话我们自定义的组件的标签就是my-picker了,然后呢我们在页面里边使用他

index
1
<my-picker class="picker" bindmyevent="onMyEventStart"></my-picker>

组件的通讯

这个组件是日期时间选择器嘛,所以得获取到选择好的时间,这里是这么写的

picker
1
2
3
4
changeDateTime(e) {
var myEventDetail = e.currentTarget.dataset.time;
this.triggerEvent('myevent', myEventDetail)
}

我们通过 myevent这个事件,将值 myEventDetail传入页面中。页面接收的方法是这样的

index
1
<my-picker class="picker" bindmyevent="onMyEventStart"></my-picker>

bindmyevent 绑定了 ‘myevent’ 这个事件,这个事件如果触发了,执行onMyEventStart 方法

index
1
2
3
4
5
6
// 活动开始时间
onMyEventStart: function (e) {
this.setData({
dateStart: e.detail
})
},

如果需要多次调用这个组件的话,只要改变他的函数即可

index
1
2
<my-picker class="picker" bindmyevent="onMyEventStart"></my-picker> 
<my-picker class="picker" bindmyevent="onMyEventEnd"></my-picker>
1
2
3
4
5
6
7
8
9
10
11
12
// 活动开始时间
onMyEventStart: function (e) {
this.setData({
dateStart: e.detail
})
},
// 活动结束时间
onMyEventEnd: function (e) {
this.setData({
dateEnd: e.detail
})
},
效果

image

有点多,毕竟结合和两个模块,本想着要不分开写的,想想连着写效果还是好点。这里的代码复制过去应该能直接拿来用吧。好了今天就说到这里了,谢谢能看到最后的兄弟,希望能帮得到大家。