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

React受控组件输入值格式化:添加千分位逗号的实现方案咨询

React受控组件实现千分位输入的解决方案

要解决受控组件中千分位格式化后光标跳转的问题,核心是在格式化文本后精准恢复光标位置,以下是具体实现方案:

实现思路

  1. 保留输入框的DOM引用,用于后续操作光标
  2. 处理输入时,先记录当前光标位置
  3. 提取输入中的纯数字并格式化为千分位格式
  4. 根据原始光标前的数字数量,计算格式化后的光标位置
  5. 在组件更新后,将光标恢复到计算后的正确位置

完整代码

import { useState, useRef, useEffect } from 'react';

const NumberInput = () => {
    const [value, setValue] = useState('');
    const inputRef = useRef(null);
    const [cursorPos, setCursorPos] = useState(0);

    const handleChange = (event) => {
        const inputValue = event.target.value;
        const selectionStart = event.target.selectionStart;
        
        // 过滤非数字字符,保留纯数字
        const rawDigits = inputValue.replace(/\D/g, '');
        // 给纯数字添加千分位逗号
        const formattedValue = rawDigits.replace(/\B(?=(\d{3})+(?!\d))/g, ',');

        // 计算原始光标位置前的数字总数
        const digitsBeforeCursor = inputValue.slice(0, selectionStart).replace(/\D/g, '').length;
        // 计算格式化后光标应处的位置:数字数 + 前面的逗号数量
        let newCursorPos = digitsBeforeCursor + Math.floor((digitsBeforeCursor - 1) / 3);
        // 处理边界:光标不能超出文本长度
        newCursorPos = Math.min(newCursorPos, formattedValue.length);

        setValue(formattedValue);
        setCursorPos(newCursorPos);
    };

    // 当输入值或光标位置更新后,恢复光标到正确位置
    useEffect(() => {
        if (inputRef.current) {
            inputRef.current.setSelectionRange(cursorPos, cursorPos);
        }
    }, [value, cursorPos]);

    return <input type="text" ref={inputRef} value={value} onChange={handleChange} />;
};

export default NumberInput;

关键细节说明

  • 光标位置计算:通过统计原始光标前的数字数量,结合千分位逗号的规律(每3个数字添加一个逗号),计算出格式化后的光标位置,确保光标始终跟随用户输入的位置
  • 受控组件规范:全程通过useState管理输入值,没有直接修改event.target.value,符合React受控组件的设计要求
  • 边界处理:处理了输入为空、光标在末尾等极端情况,避免光标位置越界

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:13:15