antd 两个DatePicker时间框实现时间动态限制

需求说明:
某个查询条件的时间选择需要限定是一个月内。即如果开始时间为2021-11-17 11:11:11,则结束时间最晚只能选2021-12-17 11:11:11
开始时间和结束时间相互限制
本来是用RangePicker的,但是看了网上的一些方法,感觉RangePicker不能完美实现,所以这里采用两个DatePicker时间框实现

最终效果:
开始时间根据结束时间,日期和时刻都都有限制。因为结束时间是2021-12-17 02:02:02,所以开始时间最早不能早于2021-11-17 02:02:02
在这里插入图片描述
开始时间最晚不能晚于2021-12-17 02:02:02
在这里插入图片描述
结束时间根据开始时间同理动态限制。最早不能早于开始时间,最晚不能晚于开始时间的后30天的时刻。
此处的天数也可动态修改

代码如下:

  state = {
    limitBeginDate: '', // 记录开始时间
    limitEndDate: '', // 记录结束时间
  }

render里的代码:

    const time = type => {
      if (this.state[type]) {
        return moment(this.state[type]).format('HH:mm:ss');
      }
      return '00:00:00';
    };
	
			<Col span={5}>
              <Form.Item label="处理时限" labelCol={{ span: 13 }} wrapperCol={{ span: 11 }}>
                {getFieldDecorator('limitBeginDate')(
                  <DatePicker
                    showTime={{ defaultValue: moment(time('limitEndDate'), 'HH:mm:ss') }} // 此处必须设置,否则可能出现添加了时间限制但是由于时间框继承之前的时刻导致时刻超出的情况
                    placeholder="Select Time"
                    allowClear={false}
                    onChange={(data, value) => { this.onChangeBeginTime(data, value, 'limitBeginDate', 'limitEndDate'); }}
                    disabledDate={this.disabledLimitBeginDate}
                    disabledTime={this.disabledLimitBeginTime}
                  />
                )}
              </Form.Item>
            </Col>
            <Col span={3}>
              <Form.Item wrapperCol={{ span: 21 }} style={{ marginLeft: 20 }}>
                {getFieldDecorator('limitEndDate')(
                  <DatePicker
                    showTime={{ defaultValue: moment(time('limitBeginDate'), 'HH:mm:ss') }}
                    placeholder="Select Time"
                    allowClear={false}
                    onChange={(data, value) => { this.onChangeEndTime(data, value, 'limitBeginDate', 'limitEndDate'); }}
                    disabledDate={this.disabledLimitEndDate}
                    disabledTime={this.disabledLimitEndTime}
                  />
                )}
              </Form.Item>
            </Col>

真正实现方法:
1、开始时间选择触发方法。注:此处把修改的数据做了抽离,当有多个类似查询条件时,只需要一个change方法即可实现,避免重复方法

  onChangeBeginTime = (data, value, beginType, endType) => {
    this.setState({
      [beginType]: value,
    });

    // 倘若结束时间为空,默认给结束时间赋值为一个月后的时候,防止只有开始时间有值,结束时间没值的情况
    if (!this.state[endType]) {
      // 获取30天后的时间
      const afterDate = this.getTheDate(value, 'after');

      this.setState({
        [endType]: afterDate,
      });
      this.props.form.setFieldsValue({
        [endType]: moment(afterDate),
      });
    }
  }

2、结束时间选择触发方法,作用与上述1的作用类似

  onChangeEndTime = (data, value, beginType, endType) => {
    this.setState({
      [endType]: value,
    });

    if (!this.state[beginType]) {
      // 获取30天前的时间
      const beforeDate = this.getTheDate(value, 'before');

      this.setState({
        [beginType]: beforeDate,
      });
      this.props.form.setFieldsValue({
        [beginType]: moment(beforeDate),
      });
    }
  }

3、开始时间的日期限制方法

  disabledLimitBeginDate = current => {
    const { limitEndDate } = this.state;
    
    if (limitEndDate) {
      // 限制前部分时间时,需多减1天
      const beforeTime = this.getTheDate(limitEndDate, 'before', 31);
      return current > moment(limitEndDate).endOf('day') || current < moment(beforeTime).endOf('day');
    }
    return null;
  }

4、开始时间的时刻限制方法。antd的DatePicker把时间和时刻的限制分成了两个方法参数,所以必须写2个限制方法

  disabledLimitBeginTime = data => {
    const { limitEndDate } = this.state;

    if (limitEndDate) {
      const endBeforeDate = moment(this.getTheDate(limitEndDate, 'before')).format('YYYY-MM-DD');
      const endDate = moment(limitEndDate).format('YYYY-MM-DD');
      const endHour = moment(limitEndDate).format('HH');
      const endMinute = moment(limitEndDate).format('mm');
      const endSecond = moment(limitEndDate).format('ss');

      if (data && data.format('YYYY-MM-DD') === endBeforeDate) {
        return {
          disabledHours: () => this.range(0, endHour),
          disabledMinutes: () => this.range(0, endMinute),
          disabledSeconds: () => this.range(0, endSecond),
        };
      }
      if (data && data.format('YYYY-MM-DD') === endDate) {
        return {
          disabledHours: () => this.range(endHour, 24),
          disabledMinutes: () => this.range(endMinute, 60),
          disabledSeconds: () => this.range(endSecond, 60),
        };
      }
    }
    return null;
  }

5、结束时间的日期限制方法。

  disabledLimitEndDate = current => {
    const { limitBeginDate } = this.state;
    
    if (limitBeginDate) {
      const afterTime = this.getTheDate(limitBeginDate, 'after');
      // 限制前部分时间时,需多减1天
      const beforeTime = this.getTheDate(limitBeginDate, 'before', 1);
      return current < moment(beforeTime).endOf('day') || current > moment(afterTime).endOf('day');
    }
    return null;
  }

6、结束时间的时刻限制方法。

  disabledLimitEndTime = data => {
    const { limitBeginDate } = this.state;

    if (limitBeginDate) {
      const beginAfterDate = moment(this.getTheDate(limitBeginDate, 'after')).format('YYYY-MM-DD');
      const beginDate = moment(limitBeginDate).format('YYYY-MM-DD');
      const beginHour = moment(limitBeginDate).format('HH');
      const beginMinute = moment(limitBeginDate).format('mm');
      const beginSecond = moment(limitBeginDate).format('ss');

      if (data && data.format('YYYY-MM-DD') === beginAfterDate) {
        return {
          disabledHours: () => this.range(beginHour, 24),
          disabledMinutes: () => this.range(beginMinute, 60),
          disabledSeconds: () => this.range(beginSecond, 60),
        };
      }
      if (data && data.format('YYYY-MM-DD') === beginDate) {
        return {
          disabledHours: () => this.range(0, beginHour),
          disabledMinutes: () => this.range(0, beginMinute),
          disabledSeconds: () => this.range(0, beginSecond),
        };
      }
    }
    return null;
  }

7、上面使用到的.已知指定时间,获取30天前或30天后的时间,此处天数可根据情况修改。参数和返回格式都是yyyy-mm-dd HH:mm:ss

  getTheDate = (date, type, time = 30) => {
    const date1 = new Date(date); // yyyy-mm-dd转中国标准日期
    const date2 = new Date(date1);

    if (type === 'after') { // 获取30天后的日期
      date2.setDate(date1.getDate() + time);
    }
    if (type === 'before') { // 获取30天前的日期
      date2.setDate(date1.getDate() - time);
    }

    return `${date2.getFullYear()}-${date2.getMonth() + 1}-${date2.getDate()} ${date2.getHours()}:${date2.getMinutes()}:${date2.getSeconds()}`;
  }

8、遍历两个值中的所有值

  range = (start, end) => {
    const result = [];
    // eslint-disable-next-line no-plusplus
    for (let i = start; i < end; i++) {
      result.push(i);
    }
    return result;
  }

以上,可完美实现限制功能。
但是有缺陷。
1、使用了两个DatePicker,美观度来说肯定是不如RangePicker的
2、个人觉得代码量过多,而且只有onChange方法可进行抽离参数重复使用,限制时间和限制时刻的方法我试过不能进行抽取,只能每个时间框都加两个方法。这就导致如果页面有多个这种时间限制的情况的时候,代码量会很冗余

下方附带在本次研究时间限制过程中弄明白的一些时间关系的切换方式
在这里插入图片描述
1、yyyy-mm-dd hh:mm:ss转中国标准时间格式
new Date(‘yyyy-mm-dd hh:mm:ss’)

2、中国标准时间格式转yyyy-mm-dd hh:mm:ss
console.log(${date2.getFullYear()}-${date2.getMonth()+1}-${date2.getDate()} ${date2.getHours()}:${date2.getMinutes()}:${date2.getSeconds()});

3、 moment转yyyy…
testMoment.format(‘YYYY-MM-DD HH:mm:ss’)

4、 yyyy转moment
moment(‘yyyy’)

5、 获取指定日期三十天后的日期(中国标准格式)
const date1 = new Date(‘yyyy-mm-dd’); // yyyy-mm-dd转中国标准日期
const date2 = new Date(date1);
date2.setDate(date1.getDate() + 30);
date2即为结果

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
antdDatePicker组件也可以通过类似的方式实现清空功能。antdDatePicker组件提供了一个allowClear属性,设置为true时就可以显示清空按钮。在清空按钮的点击事件中,可以将DatePicker组件的值设置为null或默认值。 示例代码: ``` import React, { useState } from 'react'; import { DatePicker } from 'antd'; function App() { const [date, setDate] = useState(null); const handleClear = () => { setDate(null); }; return ( <> <DatePicker value={date} onChange={value => setDate(value)} allowClear /> <button onClick={handleClear}>清空</button> </> ); } export default App; ``` 在这个示例中,另一个需要注意的点是,antdDatePicker组件的值是一个Moment.js对象,而不是一个Date对象。因此,在onChange事件中获取到的value是一个Moment.js对象。如果需要将其转换为Date对象,可以使用toDate方法,例如:value.toDate()。 另外,antdDatePicker组件还提供了一个ref属性,可以通过获取到这个ref来调用DatePicker组件的方法,包括clear方法。使用方式与React中的示例类似。 示例代码: ``` import React, { useRef } from 'react'; import { DatePicker } from 'antd'; function App() { const datePickerRef = useRef(null); const handleClear = () => { datePickerRef.current.clear(); }; return ( <> <DatePicker ref={datePickerRef} allowClear /> <button onClick={handleClear}>清空</button> </> ); } export default App; ``` 以上是在React中使用antdDatePicker组件实现清空功能的方法,可以根据实际需要选择适合自己的方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值