在 React 中处理真正的“change”事件

Qwe*_*tiy 5 javascript onchange dom-events reactjs

在 javascript 中,如果输入失去焦点或用户使用向上或向下功能,但在正常打字时不会发生input这种change情况。type="number"

document.querySelector("input").addEventListener("change", e => {
  console.log(e.type, e.target.value)
})
Run Code Online (Sandbox Code Playgroud)
<input type="number" step="0.01"> <button>&nbsp;</button>
Run Code Online (Sandbox Code Playgroud)

但是当我使用 React 时,它会逐个替换打字时发生的事件change:input

function App() {
  const [val, setVal] = React.useState("")
  
  function onChange(e) {
    console.log(e.type, e.nativeEvent.type, e.target.value)
    setVal(e.target.value)
  }
  
  return <input type="number" step="0.01" value={val} onChange={onChange} />
}

ReactDOM.render(<App />, document.getElementById("app"))
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="//unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="//unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<span id="app"></span> <button>&nbsp;</button>
Run Code Online (Sandbox Code Playgroud)

我需要处理change打字时不会发生的正常事件。
我怎样才能在反应中做到这一点?

PS:片段中的按钮是您可以tab从input.

是的,“输入时会导致编辑值出现问题”部分确实有一点帮助,尽管对我来说这似乎是代码味道,也许是 XY 问题。onChange你能分享一下在正常的 React 方式下使用时输入内容是如何导致问题的吗?

我不想完全拒绝使用它,我只是想两者都使用。

这是一个有问题的示例:

  • 小数部分不能使用退格键(除非 yeu 输入的小数位数超过 2 位)
  • 如果在小数部分使用删除,则添加零并且光标跳到末尾
  • 如果当前值为数字,并且1.<cursor>20您键入一个数字,则光标跳到末尾
  • 如果当前值类似于<cursor>1000.00您按删除键,则数字将变为0.00
  • 如果你尝试输入一个空的输入,在按下第一个数字后,它会变得像7.00<cursor>7.23 这样的东西很难输入
  • 0.00在您选择全部内容之前,要删除输入中的所有值并不困难
  • 我觉得还有很多问题

function App() {
  const [val, setVal] = React.useState("")
  
  function onChange(e) {
    console.log(e.type, e.nativeEvent.type, e.target.value)

    setVal(e.target.value == +e.target.valueAsNumber.toFixed(2)
      ? e.target.valueAsNumber.toFixed(2)
      : e.target.value
    )
  }
  
  return <input type="number" step="0.01" value={val} onChange={onChange} />
}

ReactDOM.render(<App />, document.getElementById("app"))
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="//unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="//unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<span id="app"></span> <button>&nbsp;</button>
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用onBlurfpr 格式,它会变得更好,但是:

  • step up当您单击或step down按钮或按up键盘上的或 时,数字不会被格式化,down效果相同:

function App() {
  const [val, setVal] = React.useState("")
  
  function onChange(e) {
    console.log(e.type, e.nativeEvent.type, e.target.value)
    setVal(e.target.value)
  }
  
  function onBlur(e) {
    console.log(e.type, e.nativeEvent.type, e.target.value)
    if (e.target.value && e.target.value == +e.target.valueAsNumber.toFixed(2)) {
      setVal(e.target.valueAsNumber.toFixed(2))
    }
  }
  
  return <input type="number" step="0.01" value={val} onChange={onChange} onBlur={onBlur} />
}

ReactDOM.render(<App />, document.getElementById("app"))
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="//unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="//unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<span id="app"></span> <button>&nbsp;</button>
Run Code Online (Sandbox Code Playgroud)

所以我想change在模糊和步骤中使用它。

Ant*_*una 1

这是拦截所有感兴趣的输入类型的方法,链接到codesandbox - > https://codesandbox.io/s/summer-resonance-58n15?file=/src/App.js:

function App() {
  const [val, setVal] = React.useState("");

  function onChange(e) {
    if (e.nativeEvent.inputType === "insertText") {
      console.log("input");
      // Warning: Using undefined would also comprehend other events
      // that may be not specified right now in the documentation, 
      // but could be emitted, hence causing bugs.
      // Maybe a possible future improvement could be to specify
      // this particular inputType.
    } else if (e.nativeEvent.inputType === undefined) {
      if (e.target.value > val) {
        console.log("step up");
      } else {
        console.log("step down");
      }
    } else if (e.nativeEvent.inputType === "deleteContent") {
      console.log("deleting");
    }
    setVal(e.target.value);
  }

  return (
    <React.Fragment>
      <input type="number" step="0.1" value={val} onChange={onChange} />{" "}
      <button>&nbsp;</button>
    </React.Fragment>
  );
}
Run Code Online (Sandbox Code Playgroud)