在 React 中对数字输入使用 toFloat 和 setState

Using toFloat and setState on number input in React

我有一个数字输入字段,它通过用户输入时的状态设置新值。这很好用。但是,如果我向它添加小数点 (toFixed),则光标将在仅键入一位数字后跳到输入的末尾。例如,当我删除那里的内容并输入其他内容时,就会发生这种情况。如果我改为在第一个和小数点之间添加一个数字,则光标不会跳转。有没有人以前遇到过这种情况,解决方案是什么?

Fiddle 显示问题:https://jsfiddle.net/Inverness/k04yvq1u/

constructor() {
    super()

    this.state = {
      number: 1
    }

    this.handleInputChange = this.handleInputChange.bind(this)
  }

  handleInputChange(event) {
    console.log(event.target.value)
    this.setState({
      number: event.target.value
    })
  }

  render() {
    return (
      <div>
        <input
          type="number"
          value={ parseFloat(this.state.number).toFixed(2) }
          onChange={ this.handleInputChange }
          />
      </div>
    )
  }

我遇到过类似的事情。这里的主要问题是您正在重新格式化他们键入的内容。由于 React 是使用 javascript 来改变值,浏览器无法猜测光标应该去哪里,所以它只是跳到最后。我解决这个问题的方法是仅在用户输入与 toFixed 格式匹配的内容时进行更新。在您的输入上设置 value={this.state.number} 大致等效的应该起作用的东西。然后 on change 应该看起来像这样:

handleInputChange = e => {
  let val = e.target.value
  if (/^[\d]*\.?[\d]{0,2}$/.test(val)) {
    this.setState({number: val})
  }
}

这样输入值仍然被限制为两位小数浮点格式,但用户可以更自由地键入它。

我已经成功地使用 onBlur 事件处理程序在用户完成输入后将输入字段简单地格式化为您需要的方式。

在表单字段标签中添加一些信息,将输入限制为 2 个小数位,应该有助于缓解因更改用户提供的值而导致的任何 UX 问题。

 constructor() {
    super()

    this.state = {
      number: 1
    }

    this.handleInputChange = this.handleInputChange.bind(this)
    this.formatInput = this.formatInput.bind(this)
  }

  handleInputChange(event) {
    console.log(event.target.value)
    this.setState({
      number: event.target.value
    })
  }

  formatInput() {
    const num = this.state.number
    this.setState({
        number: parseFloat(num).toFixed(2)
    })
  }

  render() {
    return (
      <div>
        <input
          type="number"
          value={ this.state.number }
          onChange={ this.handleInputChange }
          onBlur={ this.formatInput }
          />
      </div>
    )
 }

JSFiddle

你的 toFixed 函数正在改变输入值,所以你的输入失去了它的光标,正如在另一个答案中提到的我建议避免改变你的输入值,你也可以尝试使用 step 属性来更好地控制您的意见。

<input
    type="number"
    step="0.01"
    value={ this.state.number }
    onChange={ this.handleInputChange }
    defaultValue={ parseFloat(this.state.number).toFixed(2) }
/>

@ryan28561 的回答是对的,但是解决方案不是。

正如他所说,javascript不会知道光标应该在哪里,所以我推荐如下:

保留输入而不进行解析,而是为输入添加样式或警告,以便用户意识到他的输入不正确。此外,在将数字用于任何任务之前,您可以对其进行格式化。

class TodoApp extends React.Component {
  constructor() {
    super()

    this.state = {
      number: '1',
      wrongInput: false, 
    }

    this.handleInputChange = this.handleInputChange.bind(this)
  }

  handleInputChange(event) {
    let val = event.target.value
    if (/^[\d]*\.?[\d]{0,2}$/.test(val)) {
        this.setState({number: val, wrongInput: false})
    } else {
        this.setState({number: val, wrongInput: true})
    }
  }

  render() {
    return (
      <div>
        <input
          //type="number"
          style={this.state.wrongInput ? { border: `solid 1px red`, outline: 'none'} : {}}
          value={this.state.number}
          onChange={ this.handleInputChange }
          />
      </div>
    )
  }
}