Ionic日期组件实现跨天选择
Yakim Zhang

开发中需要用户在日历上进行跨天连续选择,查了半天文档,IonDatetime 组件既然不支持,那就自己动手来实现。

开发的项目中用到了 Ionic 一个跨端的框架,国内使用的人比较少,用起来整体体验很不错,一份代码可以分别在安卓、iOS、PC 上跑。底层通过 capacitor 作为桥接连接原生的 API 来实现各种功能。

缺点在于自带的 ionic 组件库比较简陋,组件缺少很多功能。

给 IonDatetime 组件添加跨天选择功能

1、增加 IonDatetime 组件

1
2
3
4
5
6
7
8
9
10
11
<div className="datePicker">
<IonDatetime
min={moment().format()}
id="date"
presentation="date"
multiple={true}
></IonDatetime>
<IonButton fill="clear" onClick={reset}>
Reset
</IonButton>
</div>

2、增加 onIonChange 事件,监听用户的选择

onIonChange 中 event 会把组件的 dom 对象传给自定义的函数。
增加 ref 挂到 IonDatetime 组件上,用来获取组件的 dom 对象。

1
2
3
4
5
6
7
8
9
10
11
12
const datetime = useRef<null | HTMLIonDatetimeElement>(null);
.....
<IonDatetime
onIonChange={(event) => {
dateChange(event);
}}
ref={datetime}
min={moment().format()}
id="date"
presentation="date"
multiple={true}
></IonDatetime>;

3、实现跨天选择

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
// 备份要修改的日期
const backupDate = useRef<string[]>([]);

function dateChange(event: any) {
// 如果当前选中的日期和备份的相同,代表不同处理
if (arrayVlaueEqual(backupDate.current, event.detail.value)) return;
// 如果选择的日期大于1个,则判断是否要跨天选择
if (event.detail.value.length > 1) {
// 如果当前日期组件不存在,则不处理
if (!datetime.current) return;
const currentValue = event.detail.value;
// 计算2个日期的所有天
const dateRange = getDiffDate(
currentValue[0],
currentValue[currentValue.length - 1]
);
// 将所有天 备份起来
backupDate.current = dateRange;
// 将value设置为计算的所有天
datetime.current.value = dateRange;
}
}

// 比较两个数组是否相等
function arrayVlaueEqual(a: any[], b: any[]) {
return a.length === b.length && a.filter((t) => !b.includes(t)).length === 0
? true
: false;
}

// 获取两个日期之间所有的天数
function getDiffDate(start: string, end: string) {
var startTime = new Date(start);
var endTime = new Date(end);
var dateArr = [];
while (endTime.getTime() - startTime.getTime() > 0) {
var year = startTime.getFullYear();
var month =
(startTime.getMonth() + 1).toString().length === 1
? "0" + (parseInt(startTime.getMonth().toString(), 10) + 1)
: startTime.getMonth() + 1;
var day =
startTime.getDate().toString().length === 1
? "0" + startTime.getDate()
: startTime.getDate();
dateArr.push(year + "-" + month + "-" + day);
startTime.setDate(startTime.getDate() + 1);
}
dateArr.push(end);
return dateArr;
}