antd日期组件时间范围动态跟随

news2025/1/9 14:28:57

这周遇到了一个很诡异但又很合理的需求。掉了一周头发,死了很多脑细胞终于上线了。必须总结一下,不然对不起自己哈哈哈。

一、需求描述

默认当前日期时间不可清空。

功能

默认时间如下:

目的:将时间改为 2014-08-01 ~ 2014-08-12

antd交互

修改开始时间为 2014-08-01,结束时间的时间选择范围首先弹出的是 2014 年 12月 和 2015年1月。

 也就是说,当改变开始时间后,跳转到结束日期时,日期选择面板根据当前时间而定的。

但实际上,这是非常逆人性化的。

因为,当我们修改时间的时候,往往第二个时间的修改是依赖于第一个选择的时间的。

需求交互

于是,产品就提出了,希望,选择第二个时间的时候,展示的时间范围根据第一个选择的时间而定。
即当修改开始时间为 2014-08-01,结束时间的时间选择范围首先弹出的是 2014年 08月 和 2015年 09 月。

 好,希望我把需求描述清楚了。 

文字再解释一遍:

比如:
当前功能:当前选择时间为:2015-01-01 至 2015-01-01,
修改开始时间为 2014-08-01,结束时间的时间选择范围首先弹出的是 2014 年 12月 和 2015年1月。
期待功能:
修改开始时间为 2014-08-01,结束时间的时间选择范围首先弹出的是 2014年 8月 和 2014年 9 月。

二、解决方法

在看了一天日期组件的api之后,我终于找到了 使时间范围自动调整的方法。 那就是在 focus 的时候,清空当前时间。

所以解决的思路就很明确了,在 onFocus 事件中清空 当前时间。

下面我就在代码中,解释思路。

import React, { useEffect, useState } from "react";
import "./index.css";
import type { DatePickerProps } from "antd";
import { DatePicker, Space } from "antd";
import dayjs from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";
import isBetween from "dayjs/plugin/isBetween";
dayjs.extend(customParseFormat);
dayjs.extend(isBetween);

const { RangePicker } = DatePicker;

const dateFormat = "YYYY/MM/DD";

const App: React.FC = () => {
  const [rangValue, setRangValue] = useState([
    dayjs(),
    dayjs().add(2, "month")
  ]) as any;

  const [originValue, setOriValue] = useState(rangValue);

  const onFocus = (f: any) => {
    // 获取当前聚焦的值(不同的环境可能聚焦的值存的位置不同,要打印出来看看哪个属性是当前值)
    const value = f.srcElement._value;

    const isStart =
      dayjs(rangValue[0]).format(dateFormat) ===
      dayjs(value).format(dateFormat);

    // 聚焦在哪一个,就清空哪一个
    setRangValue([isStart ? "" : rangValue[0], isStart ? rangValue[1] : ""]);
  };

  // 清空之后如果用户不选择当前时间,则当前时间会被清空。 所以,要在 blur 的时候 用缓存下来的上次数据去补齐
  const onBlur = (b) => {
    setRangValue([
      rangValue[0] || originValue[0],
      rangValue[1] || originValue[1]
    ]);
    setOriValue(rangValue);
  };

  // 用户有两种关闭形式,一种是跳转到另一个时间选择框,一种是鼠标点击其他区域,时间范围选择框自动关掉。于是,需要在时间范围选择框关掉的时候,再次补齐
  const onOpenChange = (open) => {
    if (!open) {
      setRangValue([
        rangValue[0] || originValue[0],
        rangValue[1] || originValue[1]
      ]);
      setOriValue(rangValue);
    }
  };

  return (
    <Space direction="vertical" size={12}>
      <RangePicker
        value={rangValue}
        format={dateFormat}
        onFocus={onFocus}
        onBlur={onBlur}
        onOpenChange={onOpenChange}
      />
    </Space>
  );
};

export default App;

以上就是这个需求的解决思路,但是这个解决方法是存在一些风险的。

即,在focus 事件中能否判断出当前focus 的是开始时间还是结束时间。

于是,我给antd 官方提了issue,希望新增加一个数据,去实现该跟随功能,或者在onfocus事件中多暴露一个参数。

欢迎大家前去支持: 日期组件时间范围动态跟随(can rangepicker component provied prop to achieve paneltime dynamically followed pre chosen time) · Issue #40680 · ant-design/ant-design · GitHub

三、解决问题过程

讲完了需求解决的思路和风险,透露一下我做这个需求的心路历程。

1、需求沟通

首先,这个需求其实很小,产品用一句话描述。 我看了几遍,都没有理解,得耗费了10分钟去跟产品沟通他要的交互和效果。

2、看文档

沟通清楚了需求,我觉得这个需求很合理,antd 应该有支持,翻翻文档,半小时内就能解决。

3、方法尝试

① 尝试属性:defaultpickValue,后发现defaultpickvalue 仅在第一次点击的时候生效。

② 尝试 在 onCalendarchange 重新设置 时间,更改之后dom 不更新。

③ 尝试 disabledate,使除了第一次选择的时间之外的相邻月份外全部disable, 无效。

经过了以上三种方式的尝试,我 finally 看到了onfocus 属性,抱着试一试的属性,他生效了!!! 

4、收尾

今天也跟同事针对这个问题进行了讨论,

问题1: 为什么在oncalendarchange 中修改绑定的时间不生效?

最后的结论是,在oncalendarchange 触发后,自动触发了 input 函数的 onChange, 而在calendar中改变的时间,没有更新,onChange 函数拿到的还是旧的值。

也就是说,onchange 把 oncalendar 中的修改覆盖了。

问题2: 为什么要用兜底?这样不绕吗?

这个问题很尴尬哈哈哈,因为,这是业务需求的,时间不能清空。 所以需要补齐时间。

5、复盘

其实这个问题的解决过程还是太长了。 一是对api 的熟悉度不高,二是,缺乏经验无法描述出最核心的问题。

在后面确认使用 onfocus 以后,以及探讨问题1 的时候,在stackoverflow 发现了一些类似的问题。

比如: reactjs - how to set start or end date of antD rangePicker to empty - Stack Overflow

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络工程师测试命令排行榜,快来看一看吧! -ccie网络工程师

网络工程师测试命令排行榜&#xff0c;快来看一看吧&#xff01; 01 Ping命令 ping命令的主要功能是用来检测网络的连通情况和分析网络运行速度。它是基于TCP/IP协议、通过发送和接收数据包来检测两台计算机间的连接状况。 网络工程师用 ping查看网络情况&#xff0c;主要…

【无标题】tcpdump 命令

tcp一款sniffer工具&#xff0c;是Linux上的抓包工具&#xff0c;嗅探器语法tcpdump (选项)选项-c&#xff1a; 指定要抓取的包数量。注意&#xff0c;是最终要获取这么多个包。例如&#xff0c;指定"-c 10"将获取10个包&#xff0c;但可能已经处理了100个包&#xf…

如何基于声网互动白板实现一个多人数独游戏

本文作者是声网社区的开发者“tjss”。他基于 Vue、声网的互动白板的代码模板&#xff0c;搭建出了一个支持多人互动的数独游戏。本文记录了他的实现过程&#xff0c;欢迎大家也可以尝试实现自己的小游戏或应用。 我基于声网互动白板的 SDK 与 Window Manager 开发了一个场景化…

第二十三周周报

学习内容&#xff1a; 修改ViTGAN代码 学习时间&#xff1a; 2.3-2.10 学习产出&#xff1a; 现在的效果 可以看到在700k左右fid开始上升&#xff0c;相比vitgan&#xff0c;改的vitgan鉴别器loss有所下降&#xff0c;但是fid没有降下来&#xff0c;最好为23.134&#xf…

Elasticsearch7.8.0版本进阶——分布式集群(水平扩容)

目录一、Elasticsearch集群的安装1.1、Elasticsearch集群的安装&#xff08;win10环境&#xff09;1.2、Elasticsearch集群的安装&#xff08;linux环境&#xff09;二、水平扩容&#xff08;win10环境集群演示&#xff09;三、想要扩容超过 6 个节点怎么办3.1、主分片和副分片…

IDEA合并分支(从开发分支到测试分支)

IDEA合并分支(从开发分支到测试分支) 1、先在当前分支拉去最新的代码且提交自己的修改到远程分支上 2、切换到目标分支(你要合并到的分支上),test测试分支 3、进行分支合并,这里其实有3个选项比较常用 ①Compare with ‘test’ 与当前分支(test)比较,这个比较回弹出个窗口…

刷爆网络的ChatGpt,给大家搞来了。

最近chatgpt可谓是顶上了热搜&#xff0c;之前写代码的同学们应该都知道出了一款插件叫做 Copilot&#xff0c;这是一款可以帮你自动写代码的插件&#xff0c;只要输入你想要写的代码&#xff0c;比如写一个js轮播图之类的&#xff0c;立马就可以帮你生成。不仅如此&#xff0c…

随着攻击者适应绕过零信任,公司在苦苦挣扎

商业情报公司 Gartner 表示&#xff0c;零信任安全方法有望减少威胁并降低成功攻击的破坏性&#xff0c;但公司不应期望实施零信任原则会很容易或阻止大多数攻击。 虽然对零信任架构的兴趣很高&#xff0c;但目前只有大约 1% 的组织拥有满足零信任定义的成熟程序。 该公司还估…

论文投稿指南——中文核心期刊推荐(石油、天然气工业 2)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

【火电机组、风能、储能】高比例风电电力系统储能运行及配置分析(Matlab代码实现)

目录 摘 要 0 目标函数和约束条件 1 第一题 2 第二题 3 第三题 4 第四题&#xff1a;含高比例风电电力系统最小供电成本模型 6 第六题&#xff1a; 7 第七题&#xff1a; 8 所有题代码及文章详细讲解 9 结论&#xff1a; 10 参考文献 摘 要 高比例风电电力系统储…

JVM——运行期优化

目录一、分层编译&#xff08;TieredCompilation&#xff09;即时编译器&#xff08;JIT&#xff09;与解释器的区别逃逸分析二、方法内联&#xff08;Inlining&#xff09;三、反射优化一、分层编译&#xff08;TieredCompilation&#xff09; JVM 将执行状态分成了 5 个层次…

宜家EDI IFTMBC运输预定确认详解

IFTMBC是宜家与其供应商之间传输的符合EDIFACT标准的报文&#xff0c;在此前的文章如何读懂EDIFACT报文中&#xff0c;我们已经对EDIFACT做了详细的解读。在供应商发给宜家IFTMBF运输预定请求后&#xff0c;宜家会回复IFTMBC运输预订确认给供应商。 本文将从供应商接收宜家发送…

【Java|golang】1798. 你能构造出连续值的最大数目

给你一个长度为 n 的整数数组 coins &#xff0c;它代表你拥有的 n 个硬币。第 i 个硬币的值为 coins[i] 。如果你从这些硬币中选出一部分硬币&#xff0c;它们的和为 x &#xff0c;那么称&#xff0c;你可以 构造 出 x 。 请返回从 0 开始&#xff08;包括 0 &#xff09;&a…

预处理和宏

1.预处理的基本概念 C语言对源程序处理的四个步骤&#xff1a;预处理、编译、汇编、链接。 预处理是在程序源代码被编译之前&#xff0c;由预处理器&#xff08;Preprocessor&#xff09;对程序源代码进行的处理。这个过程并不对程序的源代码语法进行解析&#xff0c;但它会把…

EL表达式

EL的概念JSP表达式语言&#xff08;EL&#xff09;使得访问存储在JavaBean中的数据变得非常简单。EL的作用用于替换作用域对象.getAttribute("name");3. EL的应用&#xff08;获取基本类型、字符串&#xff09;既可以用来创建算术表达式也可以用来创建逻辑表达式。在…

stm32f407探索者开发板(十四)——IO引脚复用和映射

文章目录一、端口复用二、STM32F4的端口复用映射原理三、复用功能映射设置四、端口复用配置过程一、端口复用 端口复用和重映射都是和单片机的I/O口有关系&#xff0c;端口复用是将一个I/O赋予多个功能&#xff0c;通过设置I/O的工作模式来切换不同的功能。重映射是将某些I/O口…

【运维有小邓】特权用户监视

解决方案简介&#xff1a; 使用EventLog Analyzer进行特权用户监控和审核内部用户活动报表企业IT网络的特权用户&#xff08;系统管理员、网络管理员和数据库管理员&#xff09;拥有比普通网络用户更多的权力。他们负责保持系统可用性。他们将有权创建新的用户配置文件并分配权…

PCIE总线

PCIE总线记录描述PCI分类与速度PCIE连接拓扑与角色PCIE接口定义PCIE数据传输方式与中断在PCIE中有两种数据传输方式&#xff1a;PCIE中断&#xff1a;PCIE协议栈与工作流程PCIE地址空间分类实例分析PCIE两种访问方式描述 PCI-Express(peripheral component interconnect expre…

Python调用API接口,实现人脸识别

人生苦短&#xff0c;我用Python 在开始之前&#xff0c;先问问大家&#xff1a; 什么是百度Aip模块&#xff1f; 百度AI平台提供了很多的API接口供开发者快速的调用运用在项目中 本文写的是使用百度AI的**在线接口SDK模块&#xff08;baidu-aip&#xff09;**进行实现人脸识…

K100多功能嵌入吞吐式电动发卡读写一体机|读卡器技术选型问答

K100多功能嵌入吞吐式电动发卡读写一体机|读卡器技术是一款带卡槽&#xff0c;支持150张标准卡存放&#xff0c;电动式发卡、读写一体&#xff0c;支持磁条卡读卡&#xff0c;发卡&#xff1b;支持符合ISO7816协议的接触式芯片卡发卡&#xff0c;读写卡&#xff1b;支持符合ISO…