Skip to content

🐛[BUG] ProFormDigit min/max 属性在特定输入下 onBlur 不生效 #9601

@haydenull

Description

@haydenull

提问前先看看:

https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md

🐛 bug 描述

ProFormDigit 设置 min/max 后,某些超出范围的值在 onBlur 时不会被收窄(clamp),行为不一致。

max 场景max={999}):

  • 输入 1234 → onBlur 后收窄到 999 ✅
  • 输入 99999 → onBlur 后保持 99999 ❌

min 场景min={100}):

  • 输入 56 → onBlur 后收窄到 100 ✅
  • 输入 10 → onBlur 后保持 10 ❌

📷 复现步骤

  1. 使用 <ProFormDigit max={999} min={1} fieldProps={{ precision: 0 }} />
  2. 在输入框中输入 99999
  3. 点击空白处(触发 onBlur)
  4. 观察输入框的值和表单值仍为 99999,未收窄到 999

🏞 期望结果

输入任意超出 min/max 范围的值,onBlur 后都应统一收窄到边界值。

💻 复现代码

CodeSandbox: https://codesandbox.io/s/tjplnz

© 版本信息

  • ProComponents 版本: 3.1.12-0
  • antd 版本: 6.3.3
  • 浏览器环境: Chrome
  • 开发环境: macOS

🚑 其他信息

根因分析

问题出在 packages/field/src/components/Digit/index.tsx 中 FieldDigit 的自定义 onBlurrc-input-number 原生 clamp 逻辑的竞争:

  1. FieldDigit 用 omit(fieldProps, ['onChange', 'onBlur']) 移除了 InputNumber 原始的 onChange/onBlur,替换为自定义版本
  2. 自定义 onBlur 中通过 proxyChange(e.target.value) 处理值后直接调用 fieldProps.onChange(),但 proxyChange 只做字符串转数字和 precision 处理,不做 min/max clamp
  3. 之后 rc-input-number 的 onBlur(绑定在外层 <div>,通过事件冒泡触发)会尝试 clamp,但其 triggerValueUpdate 中有去重逻辑:当 clamp 后的值等于内部 decimalValue 时,会跳过 onChange

不一致的具体原因

max=999 为例:

  • 输入 1234:逐字输入的中间值为 1→12→123→1234,最后一个 ≤ 999 的中间值是 123,clamp 后 999 ≠ 123 → onChange 正常触发 ✅
  • 输入 99999:中间值为 9→99→999→9999→99999,最后一个 ≤ 999 的中间值恰好是 999,clamp 后 999 === 999 → 触发去重,onChange 被跳过 ❌

min 同理:clamp 是否生效取决于「输入序列中最后一个在 [min, max] 范围内的中间值」是否恰好等于边界值。

相关 issue:#9048(ProFormDigitRange 的同源问题,已通过 #9058 修复,但该修复不涉及 ProFormDigit 的 FieldDigit)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions