改变 event.target.value (在 React 中)会产生什么后果?

Jd *_*cis 2 javascript event-handling reactjs

假设我们正在构建自定义输入组件。

在此组件中,作为示例,假设我们要将值从字符串更改为数字

const CustomInputComponent = ({ onChange, ...rest }) => {
  const onChangeHandler = (event)=>{
    // What are the consequences of doing this?
    event.target.value = parseInt(event.target.value, 10);
    onChange(event);
  }
  return <input type="text" onChange={onChangeHandler} />
}
Run Code Online (Sandbox Code Playgroud)

event.target.value这样直接变异会有什么后果呢?

Rob*_*ond 5

像这样直接改变 event.target.value 会产生什么后果?

它们正是您所期望的:输入的值更改为新值。

当然,如果您假设用户输入一个数值,则不会有任何明显的输出 - 因为尽管您将字符串覆盖event.target.value"1"数字1,但它会被强制返回输入中的字符串,因为输入值只能是字符串。

但是,如果用户输入其他内容,您会得到看起来很奇怪的结果 - 我只能假设意想不到的结果。请参阅下面的演示,其中我设置了组件的简单渲染(使用一个onChange不执行任何操作的函数 prop - 这只是为了说明组件不会崩溃,并且在这里没有任何区别),并亲自观察后果(拼写为位于片段下方)。

const CustomInputComponent = ({ onChange, ...rest }) => {
  const onChangeHandler = (event)=>{
    // What are the consequences of doing this?
    event.target.value = parseInt(event.target.value, 10);
    onChange(event);
  }
  return <input type="text" onChange={onChangeHandler} />
}

const App = () => <CustomInputComponent onChange={()=>{}} />;

ReactDOM.render(<App/>, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

  • 如前所述,如果您输入字符"1",它会按预期显示。
  • 如果您随后输入非数字字符,它根本不会出现。这是因为当您"a"在此处键入时,例如,是event.target.value"1a"并且parseInt("1a", 10)等于1。(parseInt与强制 via 不同Number,它会从字符串开头读取任何可以读取的数值,并在遇到无法解析的字符时停止处理。)因此该值设置为 ,1与原来相同前。
  • 如果您输入任何非数字内容,包括简单地删除上述内容(保留event.target.value为空字符串),或者重置为开头并输入非数字字符,则输出将变为NaN. 这是因为甚至不以数字字符开头的字符串(包括空字符串)在使用时会返回NaN(“不是数字”,尽管令人困惑的是该值具有 type number) 。parseInt

所以不,你不想这样做。

唯一的价值 - 假设你可以接受非数字输入的事情变得如此奇怪 - 似乎是允许这个道具的消费者提供一个onChange直接作用于数字的 ,而不必在内部从字符串转换为数字函数本身。这对我来说似乎是一个非常微弱的好处,原因如下:

  1. 您的组件<input type="text" />甚至没有inputmode="numeric"建议需要数字输入。绝对没有理由期望用户不想在此处键入非数字字符 - 即使您给它一个标签和描述,非常清楚地表明只允许输入数字,用户仍然会这样做(如果仅通过提交)拼写错误),并期望输入出现。您希望在这些情况下给出错误消息,而不是强制输入将其更改为其他内容。

  2. 即使这应该是一个数字输入,任何有过 HTML 和 Javascript 开发经验的人都知道它始终event.target.value是一个字符串。即使他们想用该字符串执行数字操作,他们也会完全期望自己必须转换为数字。

  3. 如果尽管有上述情况,您确实想向onChange函数 prop 提供一个事件对象,该对象具有一个目标值的数字,则可以在不改变现有事件对象的情况下完成此操作,例如如下所示:

const modifiedEvent = { ...event, target: { ...event.target, value: parseInt(event.target.value, 10) }};
onChange(modifiedEvent);
Run Code Online (Sandbox Code Playgroud)

好吧,我发现这行代码有点恶心 - 尽管你可能可以让它不那么可怕,也许使用一些专门为像这样的不可变“更新”而设计的帮助程序库。但对我来说,如果真的需要的话,这确实是另一个原因,而不是这样做。话虽如此,即使是上面的也比你所问的直接突变要好得多。event.target.value