You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React金额输入组件开发求助:自动格式化无需手动输入小数点

React金额输入组件(基于ShadCN实现)

核心思路

  • 用整数存储金额(以分为单位),彻底避开浮点精度问题
  • 仅允许输入数字键,输入的数字自动追加到数值末尾(等价于原数×10加新数字)
  • 退格时将数值÷10取整,反向还原格式
  • 实时将整数金额转换为带千分位、两位小数的字符串展示

完整代码实现

import { useState, useRef, useEffect } from 'react';
import { Input } from '@/components/ui/input';

const MoneyInput = () => {
  // 原始金额(单位:分),初始值0对应显示0.00
  const [rawAmount, setRawAmount] = useState<number>(0);
  // 输入框引用,用于控制光标位置
  const inputRef = useRef<HTMLInputElement>(null);

  // 将分格式化为带千分位的金额字符串
  const formatAmount = (cents: number): string => {
    // 转换为元并保留两位小数
    const dollars = (cents / 100).toFixed(2);
    // 给整数部分添加千分位分隔符
    return dollars.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  };

  // 处理键盘输入事件
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    // 仅允许数字键和退格键
    const allowedKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Backspace'];
    
    if (!allowedKeys.includes(e.key)) {
      e.preventDefault();
      return;
    }

    // 处理数字输入
    if (e.key >= '0' && e.key <= '9') {
      e.preventDefault();
      // 追加数字:原金额×10 + 新数字,限制最大值避免溢出
      const newRawAmount = rawAmount * 10 + parseInt(e.key, 10);
      if (newRawAmount <= 999999999) {
        setRawAmount(newRawAmount);
      }
    }

    // 处理退格删除
    if (e.key === 'Backspace') {
      e.preventDefault();
      // 反向还原:原金额÷10取整
      setRawAmount(Math.floor(rawAmount / 10));
    }
  };

  // 处理粘贴等非键盘输入场景
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 提取输入内容中的纯数字
    const pureDigits = e.target.value.replace(/\D/g, '');
    setRawAmount(pureDigits ? parseInt(pureDigits, 10) : 0);
  };

  // 更新金额后,自动将光标移到输入框末尾,保证输入流畅性
  useEffect(() => {
    if (inputRef.current) {
      inputRef.current.focus();
      inputRef.current.setSelectionRange(
        inputRef.current.value.length,
        inputRef.current.value.length
      );
    }
  }, [rawAmount]);

  return (
    <Input
      ref={inputRef}
      type="text"
      value={formatAmount(rawAmount)}
      placeholder="0.00"
      onKeyDown={handleKeyDown}
      onChange={handleChange}
    />
  );
};

export default MoneyInput;

关键细节说明

  • 整数存储:以分为单位存储金额,彻底避免0.1 + 0.2 = 0.30000000000000004这类浮点精度问题
  • 键盘拦截:直接拦截非数字、非退格的按键,避免无效字符干扰格式
  • 格式化逻辑:通过正则表达式自动给整数部分添加千分位分隔符,完全匹配需求格式
  • 光标控制:每次金额更新后自动将光标移到末尾,输入时不会出现光标跳位问题
  • 兼容粘贴:提取粘贴内容中的纯数字更新金额,容错性更强

测试效果

输入数字时:

  • 输入1 → 显示0.01
  • 输入2 → 显示0.12
  • 输入3 → 显示1.23
  • 输入4 → 显示12.34
  • 输入5 → 显示123.45
  • 输入6 → 显示1,234.56

删除时:

  • 按退格 → 1,234.56 → 123.45
  • 再按退格 → 123.45 → 12.34
  • 持续按退格会依次还原至0.00

内容的提问来源于stack exchange,提问作者everspader

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 18:35:01