首页 文章

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

提问于
浏览
5

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

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

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;

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

我理解为什么's happening (I think) and I'已经阅读了几个与JavaScript中没有丢失光标位置有关的问题(例如herehere) .

我想将光标位置存储在状态中(例如我希望这些是Presentation Components in Dan Abramov syntax),那么还有另外一种方法吗?

4 回答

  • 3

    嗨,关于github.com上的问题已经讨论了这个问题https://github.com/facebook/react/issues/955请参阅11月30日的评论

    您可能希望在输入组件上使用setstate .

  • 0

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

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

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

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

  • 5
    set value(val) { // Set by external method
        if(val != this.state.value) {
            this.setState({value: val, randKey: this.getKey()});
        }
    }
    
    getKey() {
        return 'input-key' + parseInt(Math.random() * 100000);
    }
    
    onBlur(e) {
        this.state.value = e.target.value; // Set by user
        if(this.props.blur) this.props.blur(e);
    }
    
    render() {
        return(
    <input className="te-input" type="text" defaultValue={this.state.value} onBlur={this.onBlur} key={this.state.randKey} />
        )
    }
    

    如果您需要一个既可以在没有光标移动的情况下编辑也可以从外部设置的输入,则应该使用默认值,并在外部更改值时使用不同的键渲染输入 .

  • 0
    onKeyUp(ev) {
        const cardNumber = "8318 3712 31"
        const selectionStart = ev.target.selectionStart; // save the cursor position before cursor jump
        this.setState({ cardNumber}, ()=>{
          ev.target.setSelectionRange(selectionStart, selectionStart); // set the cursor position on setState callback handler
        });
    
    }
    

    我希望这有帮助 :)

相关问题