在 Svelte 中,有没有办法在不更改状态的情况下撤消无效的用户输入?

In Svelte, is there a way to undo invalid user input, without changing the state?

在 Svelte 中,有没有一种方法可以撤消无效的用户输入,而不会触发暂时虚假的 属性 状态更改?

例如(try it online),当用户在input框中输入123a时,我想将其转换为一个数字并分配给它counter

为此,我必须对 counter 进行临时且多余的更改(使用下面的 Number.NaN)。否则,counter 不会改变,123a 将保留在 input 框内,而我想将其还原为 123:

<script>
    let count = 0;
    const handleClick = () => count++;
    const handleChange = async e => {
        const userValue = e.target.value;
        let newValue = userValue? parseInt(userValue): 0;
        if (isNaN(newValue)) newValue = count;
        count = Number.NaN;
        await Promise.resolve();
        count = newValue;           
    };  
</script>

Count: <button on:click={handleClick}>{count}</button>
<br />
A: <input value={count} on:input={handleChange} />
<br />

有更好的方法吗?本质上,我想为我的 Svetle 组件的一部分触发手动重新渲染,而不更改状态。

当然,在事件处理程序中,我可以通过直接修改 e.target.value 来撤消更改:

const handleChange = async e => {
    const userValue = e.target.value;
    let newValue = userValue? parseInt(userValue): 0;
    if (isNaN(newValue)) newValue = count;
    if (newValue == count)
        e.target.value = count;
    else
        count = newValue;
};  

但我想知道是否有办法让 Svelte 重新渲染整个 <input>

为了比较,这是我在 React 中的做法 (try it online):

function App() {
  let [count, setCount] = useState(0);
  const handleClick = () => setCount((count) => count + 1);
  const handleChange = (e) => {
    const userValue = e.target.value;
    let newValue = userValue ? parseInt(userValue) : 0;
    if (isNaN(newValue)) newValue = count;
    setCount(newValue);
  };
  return (
    <>
      Count: <button onClick={handleClick}>{count}</button>
      <br />
      A: <input value={count} onInput={handleChange} />
      <br />
    </>
  );
}

您只需要bind count to the value of the input. REPL

<script>
  let count = 0;
  
  const handleClick = () => count++;
  
  const handleChange = (e) => {
    const userValue = e.target.value;
    const newValue = userValue ? parseInt(userValue, 10) : 0;
  
    count = isNaN(newValue) ? count : newValue;
  };    
</script>

Count: <button on:click={handleClick}>{count}</button>
<br />
A: <input bind:value={count} on:input={handleChange} />
<br />

注意:记得always pass a radix to parseInt(),不是默认10。