antd 两个 DatePicker 组件实现起止时间相互约束的流程
Posted 毕小宝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了antd 两个 DatePicker 组件实现起止时间相互约束的流程相关的知识,希望对你有一定的参考价值。
背景
一个基于 React 前端技术的项目,在做搜索功能时,虽然 antd 有 DateRange
插件,但技术选择用的是两个 DatePicker
,所以需要自己实现起止时间的约束:
- 开始时间必须小于结束时间
- 结束时间必须大于开始时间,且不超过当日
实现流程
第一,定义两个成员变量和两个 state 属性:
- 两个记录当前日期插件选中的时间的变量;
- 两个 state 时间变量,初始化日期插件的变量。
第二,起止时间插件各自用到的两个回调函数:
- onChangeStart ,开始时间,选择时间变更后,记录对应值
- onChangeEnd ,结束时间,选择时间变更后,记录对应值
- disableDateStart ,开始时间回调
- disableDateEnd ,结束时间的回调
第一,全局变量定义
组件构造函数定义两个成员变量用来记录当前选择的日期,注意是成员变量,而不是 state 的两个属性。
constructor(props) {
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth() + 1 < 10 ? '0' + (now.getMonth() + 1) : now.getMonth() + 1;
let day = now.getDate() < 10 ? '0' + now.getDate() : now.getDate();
let defaultStartTime = year + "-" + month + "-" + day + " 00:00:00";
let defaultEndTime = year + "-" + month + "-" + day + " 23:59:59";
// 页面需要的常量:当天时间起止值
this.todayStart = moment(defaultStartTime);
this.todayEnd = moment(defaultEndTime);
// 页面 state 数据
this.state = {
startTime: this.todayStart,
endTime: this.todayEnd,
}
// 由于 state.xxx 属性设置后容易出现 undefined ,所以用全局类变量
this.currentStartTime = this.todayStart;
this.currentEndTime = this.todayEnd;
}
第二,日期插件引用
组件引用两个日期插件,指定初始值和各自的回调:
<Form ref={this.formRef} onFinish={this.onFinish}>
<div>开始时间</div>
<Form.Item name="startTime" initialValue={this.state.startTime}>
<DatePicker
showTime={{ format: 'HH:mm:ss' }}
format="YYYY-MM-DD HH:mm:ss"
allowClear={false}
onChange={ this.dateChangeStart}
disabledDate={this.disabledDateStart}
/>
</Form.Item>
<div>结束时间</div>
<Form.Item name="endTime" initialValue={this.state.endTime}>
<DatePicker
showTime={{ format: 'HH:mm:ss' }}
format="YYYY-MM-DD HH:mm:ss"
onChange={ this.dateChangeEnd}
disabledDate={this.disabledDateEnd}
allowClear={false}
/>
</Form.Item>
</Form>
第三,日期变动回调定义
为起止时间插件,定义 onChange
回调,如果选择了新日期,则记录到全局变量中。
// 点击都会触发该函数,未选择时是 undefiend
dateChangeStart = (current) => {
if(current != undefined) {
this.currentStartTime = current; // 修改全局变量,通知日期插件
}
}
dateChangeEnd = (current) => {
if(current != undefined) {
this.currentEndTime= current; // 修改全局变量,通知日期插件
}
}
第四,禁用时间回调定义
开始时间插件的 disabledDate
根据当前选中的结束日期值设定禁用时间,同理,结束时间插件根据开始时间和当天设定禁用范围。
详细函数定义为:
// 开始时间范围:不能包含今天以后的,且不能超过结束时间
disabledDateStart = (current) => {
const endValue = this.currentEndTime;//获取结束时间
if (!endValue) {//如果开始日期或者结束日期都没有选择,限定今日之后的不允许选择
return current && current.valueOf() > this.todayEnd.valueOf();
}
//用户选择了结束时间,则开始时间要小于结束时间
return current.valueOf() > endValue.valueOf();
}
disabledDateEnd = (current) => {
const startValue = this.currentStartTime;
const currentcurrent = this.currentEndTime;
// 如果用户未选择开始时间,则不能选今天以后的
if (!startValue) {
return current && current.valueOf() > this.todayEnd.valueOf();
}
// 时间范围在开始时间和当日之间
return current.valueOf() <= startValue.valueOf() ||
current.valueOf() > this.todayEnd.valueOf();
}
运行效果
选定开始和结束时间后,查看各自插件的选择范围:
启示录
思路很简单,就是 disableDate
回调要利用当前日期插件选择的时间,来确定范围。
有一个坑点就是 state
变量,感觉它是异步的,即使刚刚设置了值,disableDate
回调取到的却是 undefined
。
最初为了记录选中日期,将其设置为 state.curerntStartTime
,结果取值时会出现 undefined
的情况,页面选择几次日期后,禁用时间范围就乱套了。
结论:要实现两个日期插件的选择范围联动,函数中引用的变量应该定义为 this.xxx
属性,而非 this.state.xxx
。
这可能跟 state
的作用有关吧,它主要是动态回显组件值的,数值更新有滞后!
以上是关于antd 两个 DatePicker 组件实现起止时间相互约束的流程的主要内容,如果未能解决你的问题,请参考以下文章
react+antd,DatePicker组件只选择年月日,得到的时间戳不是当前日期0点
typescript使用antd中RangePicker组件实现时间限制 当前时间的前一年(365天)
typescript使用antd中RangePicker组件实现时间限制 当前时间的前一年(365天)