在React中,onChange和onInput有什么区别?


86

我已经尝试过寻找答案,但是其中大多数都在React的上下文之外,而后者onChange会在模糊时触发。

在执行各种测试时,我似乎无法分辨出这两个事件有何不同(应用于文本区域时)。谁能对此有所启发?


1
我编辑了帖子,使其更加清晰。我是在专门讲文本区域,而不是单选按钮或复选框。
ffxsam '16

这是完全错误的,React不只是JS。在某些情况下,事件的行为略有不同(例如onChange)。不,在textarea中粘贴文本(在React中)会同时触发onChangeonInput。随时进行测试,您会发现。
ffxsam 2016年

对于<input>和<textarea>,onChange取代了DOM的内置oninput事件处理程序,通常应代替它使用。
Roko C. Buljan

我认为onChange是更安全的选择。我什至尝试以编程方式更改textarea的值,认为可能onChange会触发onInput但不会触发,但两者都会触发。
ffxsam

是的,现在,在回顾了一些React Docs之后,我看到React做了很多类似jQuery的事情,它规范化了事件,是的。onChange似乎是一种首选方式。是的 React只不过是JS。没有特别的魔法。只是规则。
Roko C. Buljan '16

Answers:


79

似乎没有真正的区别

由于某种原因,React将侦听器附加Component.onChange到DOMelement.oninput事件。请参阅表单文档中的注释:

React Docs-表格

有更多的人对此行为感到惊讶。有关更多详细信息,请在React问题跟踪器上参考此问题:

记录React的onChange与onInput#3964的关系

引用关于该问题的评论:

我不明白为什么React选择使onChange表现得像onInput一样。据我所知,我们无法恢复旧的onChange行为。Docs声称这是一个“错误用语”,但事实并非如此,它会在发生更改时触发,只是直到输入也失去焦点为止。

为了进行验证,有时我们不希望在输入完毕后显示验证错误。或者,也许我们只是不想在每次击键时都重新渲染。现在唯一的方法是使用onBlur,但现在我们还需要检查该值是否已手动更改。

没什么大不了的,但是在我看来,React抛弃了一个有用的事件,并且在已经有一个事件发生时却偏离了标准行为。

我同意100%的评论...但是我想现在更改它会带来比解决方案更多的问题,因为已经编写了太多依赖此行为的代码。

React不是官方Web API集合的一部分

尽管React是基于JS构建的,并且已经获得了巨大的采用率,但是作为一种技术,React存在于其自己的(相当小的)API下隐藏了很多功能。一旦这在事件系统中很明显,那么与标准DOM事件系统根本不同的是,地下发生了很多事情。不仅根据哪个事件执行了什么操作,还根据何时允许数据保留在事件处理的哪个阶段。您可以在这里阅读更多有关此的内容:

反应事件系统


最后一段是误导/不真实的。
反弹

1
React不是一个框架(它在哪里提供路由,持久性,网络I / O管理等?),而是一个提供核心抽象的,用于通过平台特定的后端(react-dom,react-native,等等。)。
反弹

7
哇好 我有点同意它是一个库,而不是一个框架,但是因为这个原因使该段具有误导性/不真实性?我也不同意框架应该提供Web应用程序的所有方面的观点。例如,存在路由框架,或者像redux这样的状态管理框架。在我看来,框架使您可以填充运行正常的机器。在Redux的情况下,您需要填充化简器。如果是Express,则填写请求处理程序和中间件。等等,但至少可以说这是一个灰色区域。
Stijn de Witt '18

4
完全同意。争论库和框架之间的区别确实是浪费时间。取决于您所使用的抽象级别。
swyx '18

1
@chadsteele谢谢朋友,很高兴听到它对您有帮助
Stijn de Witt

21

没有区别

React没有默认的“ onChange”事件的行为。我们在react中看到的'onChange'具有默认的'onInput'事件的行为。因此,要回答您的问题,两者的反应都没有区别。我在GitHub上提出了一个与此有关的问题,这是他们不得不说的:

我认为在做出此决定(大约4年前?)时,onInput在浏览器之间无法始终如一地工作,并且使从其他平台访问Web的人们感到困惑,因为他们希望“更改”事件能够在每一个变化上开火。在React的情况下,这是一个更大的问题,因为如果您不能足够快地处理更改,则受控输入将永远不会更新,从而使人们认为React已损坏。因此,团队将其称为onChange。

回顾一下,最好将poly填充为onInput并保留其名称,而不是更改另一个事件的行为。但是那艘船已经航行很久了。我们将来可能会重新考虑这个决定,但我只鼓励您将其视为React DOM的怪癖(您会很快习惯)。

https://github.com/facebook/react/issues/9567

此外,本文还将提供更多见解。作为缺少默认“ onChange”的一种解决方法,本文建议听“ onBlur”事件。

https://www.peterbe.com/plog/onchange-in-reactjs


3

最近我遇到一个错误,该错误onChange不允许在IE11的输入字段中进行复制和粘贴。而该onInput事件将允许该行为。我在文档中找不到任何描述此内容的文档,但这确实表明两者之间存在差异(预期与否)。


2

如您在此处的各种评论中所见,React将onChange和onInput视为相同,因此,无需争论此决定的优缺点。这是解决方案。

如果您不想在完成用户编辑之前对其进行处理,请使用onBlur。:)


1

对于偶然发现此问题并寻求侦听基于DOM的实际change事件的任何人,这就是我的方法(用TypeScript编写):

import { Component, createElement, InputHTMLAttributes } from 'react';

export interface CustomInputProps {
    onChange?: (event: Event) => void;
    onInput?: (event: Event) => void;
}

/**
 * This component restores the 'onChange' and 'onInput' behavior of JavaScript.
 *
 * See:
 * - https://reactjs.org/docs/dom-elements.html#onchange
 * - https://github.com/facebook/react/issues/3964
 * - https://github.com/facebook/react/issues/9657
 * - https://github.com/facebook/react/issues/14857
 */
export class CustomInput extends Component<Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onInput' | 'ref'> & CustomInputProps> {
    private readonly registerCallbacks  = (element: HTMLInputElement | null) => {
        if (element) {
            element.onchange = this.props.onChange ? this.props.onChange : null;
            element.oninput = this.props.onInput ? this.props.onInput : null;
        }
    };

    public render() {
        return <input ref={this.registerCallbacks} {...this.props} onChange={undefined} onInput={undefined} />;
    }
}

如果您看到改进此方法或遇到问题的方法,请告诉我。与不同blurchange事件在用户按下Enter键时也会触发,并且仅在值实际更改时才触发。

我仍然在此CustomInput组件方面积累了经验。例如,复选框的行为异常。我要么在将值传递给Checkboxevent.target.checked时在onChange处理程序中反转,要么在将值传递给checkedCheckbox时摆脱了这种反转,defaultChecked但是这打破了代表页面上不同位置的相同状态的多个复选框保持同步。(在两种情况下,我都没有将onInput处理程序传递给CustomInputfor复选框。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.