前端UI组件【免费下载链接】rsuite A suite of React components .项目地址https://gitcode.com/gh_mirrors/rs/rsuite点击查看免费下载本文围绕 RSUITE 组件库中DatePicker的不可交互能力展开系统讲解如何通过disabled、shouldDisableDate、shouldDisableHour/Minute/Second、hideHours/Minutes/Seconds、readOnly与plaintext六类属性实现整个组件禁用、按天禁用、按月禁用、按时分秒禁用/隐藏以及表单场景下的只读与纯文本展示。读完本文你将能够在实际业务中精确控制日期时间选择器的可选范围并理解这些属性在 src/DatePicker/DatePicker.tsx 中的底层判定逻辑。一、五种不可交互状态的适用场景从官方示例 docs/pages/components/date-picker/fragments/disabled.md 可以看出RSUITE DatePicker 将禁止选择拆分为粒度不同的五种状态开发者可按需组合状态属性典型场景整体禁用disabled表单未满足前置条件时整块输入不可点击、不可聚焦按日期禁用shouldDisableDate节假日不可选、过去的日期不可选、仅允许当月可选按时分秒禁用shouldDisableHour/shouldDisableMinute/shouldDisableSecond预约系统只允许 8:00–18:00 之间、每 15 分钟一个档位按时分秒隐藏hideHours/hideMinutes/hideSeconds业务上根本不存在的时段直接从滚动列中移除只读 / 纯文本readOnly/plaintext详情页展示已提交数据禁止再次修改其中前四种属于选择器内部的交互约束后两种属于表单控件的展示模式。它们可以自由叠加例如同时使用disabled与readOnly也可以与format、ranges等配置协同工作。二、官方示例五种状态的一次性演示官方文档提供了一段完整的可运行示例原始片段位于 disabled.md它用一个Field组件封装了标签与选择器依次展示了全部状态import { DatePicker, VStack, HStack, Text, Divider } from rsuite; import { isBefore } from date-fns/isBefore; const Field ({ label, children, ...rest }) ( HStack Text muted w{120} {label} /Text DatePicker {...rest} w{180} / /HStack ); const App () ( VStack divider{Divider /} VStack Field labelDisabled disabled / Field labelDisabled date defaultValue{new Date()} shouldDisableDate{date isBefore(date, new Date())} / Field labelDisabled month shouldDisableDate{date { const month date.getMonth(); return month 0 || month 11; }} formatyyyy-MM / Field labelDisabled time formatHH:mm:ss ranges{[]} defaultValue{new Date(2017-12-12 09:15:30)} shouldDisableHour{hour hour 8 || hour 18} shouldDisableMinute{minute minute % 15 ! 0} shouldDisableSecond{second second % 30 ! 0} / Field labelHidden time formatHH:mm:ss ranges{[]} defaultValue{new Date(2017-12-12 09:15:30)} hideHours{hour hour 8 || hour 18} hideMinutes{minute minute % 15 ! 0} hideSeconds{second second % 30 ! 0} / /VStack Field labelRead only readOnly defaultValue{new Date()} / Field labelPlaintext plaintext defaultValue{new Date()} / /VStack );示例中的几个细节值得注意w{120}、w{180}是 RSUITE 5 基于Box体系的宽度快捷属性用于统一排版Text muted渲染灰色标签。formatyyyy-MM让选择器只呈现年月面板月份视图此时shouldDisableDate作用于月份维度。ranges{[]}传入空数组用于清空底部默认快捷按钮今天/昨天避免时间模式下快捷项干扰。若不传rangesRSUITE 会通过 src/DatePicker/utils.ts 中的getDefaultRanges自动生成today、yesterday两个默认项。时间模式下必须显式传入defaultValue否则没有可对照的当前时间来高亮选项。三、整体禁用disableddisabled是组件级开关直接作用于触发器和输入框。在 src/DatePicker/DatePicker.tsx 中可以看到它的传递链路传入PickerToggleTrigger使整个触发器含下拉展开能力失效传入InputGroup与Input使键盘输入、清空按钮同时被禁用showCleanButton cleanable hasValue !readOnly中不含disabled判断——disabled由 InputGroup 层统一拦截。这与readOnly存在本质区别disabled状态下的控件不可聚焦、不可提交值不会参与表单序列化而readOnly仍可聚焦、可复制文本值仍会随表单提交。四、按日期禁用shouldDisableDate与月份面板联动shouldDisableDate接收一个(date: Date) boolean判定函数返回true的日期在日历网格中不可选中。其底层逻辑在 src/DatePicker/DatePicker.tsx#L346-L352 的isDateDisabled中const isDateDisabled (date: Date): boolean { if (typeof shouldDisableDate function) { return shouldDisableDate(date); } return false; };值得注意的是这个函数不是只在点击时调用一次而是会被日历渲染层逐格调用用来给每个单元格打上rs-calendar-table-cell-disabled样式与aria-disabledtrue属性。对应的测试见 src/DatePicker/test/DatePicker.spec.tsx#L1133-L1152被禁用的gridcell即使被点击onSelect也不会触发。月份视图下的特殊规则当formatyyyy-MM时日历切换为月份面板此时禁用的判定粒度自动从天提升为月。源码中的isMonthDisabledDatePicker.tsx#L365-L367借助isEveryDateInMonth判断只有当月内每一天都被shouldDisableDate判定为禁用时该月份才整体禁用const isMonthDisabled (date: Date): boolean { return isEveryDateInMonth(date.getFullYear(), date.getMonth(), isDateDisabled); };因此官方示例中禁用 1 月与 12 月的写法month 0 || month 11是安全且一致的——如果一个月里只有部分日期禁用月份仍可选中这保证了能选中月与OK 按钮可用的状态始终一致对应测试见 DatePicker.spec.tsx#L1242-L1263。OK 按钮与错误态联动isOkButtonDisabledDatePicker.tsx#L375-L381会在日期模式下对选中值执行完整的isDatetimeDisabled判定日期禁用 时间禁用在月份模式下执行isMonthDisabled判定从而控制 Toolbar 中 OK 按钮的禁用。同时isErrorValue会把当前值被禁用标记为错误使组件外层获得rs-picker-error类名、输入框获得aria-invalidtrue测试见 DatePicker.spec.tsx#L1265-L1297。这意味着即便通过受控value强行传入一个被禁用的日期界面也会给出明确的错误提示而不是静默接受。五、按时分秒禁用shouldDisableHour/Minute/Second当format包含时间片段如HH:mm:ss时可以使用三个判定函数分别约束小时、分钟、秒shouldDisableHour{hour hour 8 || hour 18} // 只允许 8~18 点 shouldDisableMinute{minute minute % 15 ! 0} // 每 15 分钟一个档位 shouldDisableSecond{second second % 30 ! 0} // 每 30 秒一个档位三个函数的签名均为(value: number, date: Date) boolean第二参数传入当前选中日期便于做与日期相关的时段限制。底层实现disableTime这些属性会被汇总到isDatetimeDisabled中统一判定DatePicker.tsx#L357-L359const isDatetimeDisabled (date: Date): boolean { return isDateDisabled?.(date) || disableTime(props, date); };核心工具disableTime定义在 src/internals/utils/date/disableTime.ts。它从 props 中挑出全部时间禁用相关属性shouldDisableHour、shouldDisableMinute、shouldDisableSecond以及已废弃的disabledHours/Minutes/Seconds用正则/(Hours?)/、/(Minutes?)/、/(Seconds?)/识别属性名再分别取当前日期的getHours、getMinutes、getSeconds调用判定函数任一返回 true 即认为整个时间不可用return Array.from(mapProps.keys()).some(key { if (HOURS_PATTERN.test(key)) { return mapProps.get(key)?.(getHours(date), date); } if (MINUTES_PATTERN.test(key)) { return mapProps.get(key)?.(getMinutes(date), date); } if (SECONDS_PATTERN.test(key)) { return mapProps.get(key)?.(getSeconds(date), date); } return false; });disableTime的判定结果同时驱动三处 UI 状态时间滚动列中对应选项被标记cell-disabled并设置aria-disabledtrue点击无响应日历头部的时间切换按钮Select time获得rs-calendar-header-error错误样式Toolbar 的 OK 按钮被禁用。以上三点在 DatePicker.spec.tsx#L1187-L1240 的Disable Date, Hour, Minute, Second测试组中有完整覆盖分别验证formatHH、formatmm、formatss下选项的aria-disabled属性以及时间被禁用时 OK 按钮的disabled属性。关于已废弃的旧属性从 src/DatePicker/types.ts 可以看到早期版本的disabledDate、disabledHours、disabledMinutes、disabledSeconds均已被标记为deprecated官方推荐统一迁移到shouldDisableDate与shouldDisableHour/Minute/Second系列。新属性语义更清晰should disable 表达的是开发者提供的判定规则且与hide*系列形成完整的能力矩阵。六、按时分秒隐藏hideHours/Minute/Seconds与禁用有何不同hide*系列与shouldDisable*系列最大的区别在于渲染层面禁用shouldDisable*选项依然渲染在滚动列中但灰显、不可点击用户能看到该时段存在但被禁止隐藏hide*选项直接从滚动列中移除用户看不到该时段。该逻辑实现在 src/Calendar/TimeDropdown/TimeDropdown.tsx#L99-L133 的renderColumn中for (let i start; i end; i 1) { if (!hideFunc?.(i, plainDate)) { const disabled disabledFunc?.(i, plainDate); // ... 渲染 li roleoptiondisabled 时设置 aria-disabled } }即先判断hideFunc为true直接continue跳过渲染否则渲染选项再按disabledFunc决定是否灰显。滚动列的取值范围由 src/Calendar/TimeDropdown/utils/getTimeLimits.ts 的getTimeLimits决定24 小时制下小时为 0–23启用showMeridiem12 小时制时小时为 0–11分钟与秒恒为 0–59。从无障碍与可用性角度二者各有取舍隐藏更彻底减少无效滚动但用户无法感知被隐藏的时段禁用保留可见性便于传达规则限制。在官方示例中Disabled time与Hidden time使用了完全相同的判定条件8–18 点、15 分钟、30 秒可以直观对比两种呈现差异。七、表单态readOnly与plaintextreadOnly可聚焦但不可修改readOnly让输入框进入只读模式但视觉上仍保持表单控件外观。它的处理发生在 src/DatePicker/hooks/useCustomizedInput.ts#L27-L28let inputReadOnly: boolean readOnly || !editable || loading || false;也就是说除显式传入readOnly外editable{false}禁止键盘输入或loading加载中也会使输入框只读。只读状态下的选择器仍可展开日历查看且不会显示清空按钮showCleanButton依赖!readOnly。plaintext脱离表单外观的纯文本plaintext则完全不同它把整个组件渲染成一段普通文本彻底去掉输入框、日历触发器与边框。源码中通过条件渲染实现DatePicker.tsx#L694-L696{plaintext ? ( DateInput value{value} format{formatStr} plaintext{plaintext} / ) : ( InputGroup ....../InputGroup )}plaintext状态下值按照formatStr默认取 locale 的shortDateFormat即yyyy-MM-dd格式化输出适合在详情页、审核页等只读展示场景复用同一数据模型。与 renderValue 的配合若同时提供renderValueuseCustomizedInput会优先渲染自定义字符串useCustomizedInput.ts#L33-L39此时输入框自动转为只读确保自定义值不被键盘编辑破坏。八、组合建议与注意事项disabledvsreadOnly按语义选择需要禁止提交选disabled需要允许复制文本且值随表单提交选readOnly纯展示选plaintext。时间格式必须与判定粒度匹配只有format中包含对应字段HH/mm/ss时时/分/秒的禁用与隐藏才会生效shouldDisableHour不会影响纯日期面板。月份面板的整月禁用是聚合结果shouldDisableDate对所有日期统一判定月份是否可用由isEveryDateInMonth自动推导无需单独写月份判定。清空默认快捷项时间选择场景建议传ranges{[]}否则默认的今天/昨天快捷按钮会出现在 Toolbar。受控值被禁用时会呈现错误态不要依赖传值即生效界面会通过rs-picker-error与aria-invalid提示该值不可选配合表单校验使用效果最佳。上述全部行为均有源码与测试双重佐证组件实现见 src/DatePicker/DatePicker.tsx时间判定核心见 src/internals/utils/date/disableTime.ts时间列渲染见 src/Calendar/TimeDropdown/TimeDropdown.tsx行为验证见 src/DatePicker/test/DatePicker.spec.tsx。开发者可直接参照官方示例disabled.md将五种状态应用到自己的表单与详情页中。赞分享前端UI组件【免费下载链接】rsuite A suite of React components .项目地址https://gitcode.com/gh_mirrors/rs/rsuite点击查看免费下载相关推荐Ant Design DatePicker 实战用 disabledDate 与 disabledTime 精准禁用日期和时间Ant Design DatePicker 实战用 disabledDate 与 disabledTime 精准禁用日期和时间 本文基于 ant design前端UI组件设计系统ng-zorro-antd DatePicker 禁用状态实战nzDisabled、nzDisabledDate 与 nzDisabledTime 全解析ng zorro antd DatePicker 禁用状态实战nzDisabled、nzDisabledDate 与 nzDisabledTime 全解析 本UI组件前端Ant Design DatePicker 不可用状态完全指南disabled、RangePicker 局部禁用与 minDate/maxDate 日期范围控制Ant Design DatePicker 不可用状态完全指南disabled、RangePicker 局部禁用与 minDate/maxDate 日期范围控前端UI组件设计系统上一篇gulp-autoprefixer源码解析揭秘其工作原理与实现方式下一篇BTCRecover助记词恢复实战指南钱包密码找回与BIP38解密快速上手创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考