在React中格式化数字时停止光标跳转

tom*_*dox 11 reactjs react-jsx

我的反应组件上有一个输入字段,显示项目的行价(两个小数位,有千位分隔符).我希望当组件首次呈现时显示的值为货币格式,并且还要作为字段中的用户类型以货币格式保存.

目前我的组件中有以下代码:

var React = require('react');
import accounting from 'accounting';

MoneyInput = React.createClass({
    propTypes: {
        name: React.PropTypes.string.isRequired,
        onChange: React.PropTypes.func.isRequired,
        value: React.PropTypes.number,
        error: React.PropTypes.string,
    },

    onChange(event) {
        // get rid of any money formatting
        event.target.value = accounting.unformat(event.target.value);

        // pass the value on
        this.props.onChange(event);
    },

    getValue() {
        return accounting.formatNumber(this.props.value, 2)
    },

    render() {

        return (
                <div className="field">
                    <input type="text"
                           name={this.props.name}
                           className="form-control"
                           value={this.getValue()}
                           onChange={this.onChange} />
                    <div className="input">{this.props.error}</div>
                </div>
        );
    }
});

module.exports = MoneyInput;
Run Code Online (Sandbox Code Playgroud)

该代码显示正确格式化的数据,但每次输入值时,光标都会跳转到数字的末尾.

我理解为什么会发生这种情况(我认为),并且我在这里阅读了几个与不在JavaScript中丢失光标位置有关的问题(例如这里这里).

我想知道在React中处理这个问题的最佳方法是什么?我认为理想情况下我不希望将光标位置存储在状态中(例如,我希望这些是Dan Abramov语法中的Presentation Components),那么还有另一种方法吗?

小智 19

在React的<input />字段中放松光标/插入位置的简单解决方案是自己管理位置:

onChange(event) {

  const caret = event.target.selectionStart
  const element = event.target
  window.requestAnimationFrame(() => {
    element.selectionStart = caret
    element.selectionEnd = caret
  })

  // your code
}
Run Code Online (Sandbox Code Playgroud)

光标位置重置的原因是因为React不知道您正在执行什么类型的更改(如果您将文本完全更改为更短或更长的内容会怎样?)并且您现在负责控制插入位置.

示例:在我的一个输入文本字段中,我用省略号自动替换三个点(...).前者是三个字符长的字符串,而后者只是一个字符串.虽然React会知道最终结果会是什么样子,但它不知道将光标放在哪里,因为没有一个明确的逻辑答案.

  • 哇,这是一个简单的解决方案。干得好,就像魔术一样! (2认同)
  • 这是一个很棒的提示!我发现有一种边缘情况它无法处理——如果用户输入足够多的字符来足够快地触发更改,光标仍然可以跳到末尾。我怀疑这是因为 React 在动画帧之间多次调用 onChange 处理程序,第二次调用看到第一个调用留下的文本结束状态,然后使用该值安排动画帧。我必须敲击按键才能触发这个问题,所以我不打算尝试修复它。 (2认同)