在React中,onChange和onInput之间的区别是什么?

时间:2016-07-07 22:35:18

标签: javascript reactjs javascript-events

我已经尝试过寻找答案,但大多数都不在React的背景下,onChange会在模糊时触发。

在进行各种测试时,我似乎无法说明这两个事件是如何不同的(当应用于textarea时)。任何人都可以对此有所了解吗?

6 个答案:

答案 0 :(得分:43)

似乎没有真正的区别。

由于某种原因,React将Component.onChange的侦听器附加到DOM element.oninput事件。请参阅表格文档中的说明:

<强> React docs - Forms

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

<强> Document how React's onChange relates to onInput #3964

引用该问题的评论:

  

我不明白为什么React选择让onChange表现得像onInput一样。正如我所知,我们无法恢复旧的onChange行为。 Docs声称这是一个“用词不当”但不是不是真的,它会在发生变化时触发,直到输入也失去焦点。

     

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

     

这并不是什么大不了的事,但在我看来,就像React丢掉了一个有用的事件并且在已经发生了这样的事件时偏离了标准行为。

我同意100%的评论...但我想现在更改它会带来比它解决的更多问题,因为已经写了很多依赖于这种行为的代码(并且它也被复制到其他框架,例如Preact)。

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

尽管React是建立在JS之上的,并且已经看到了巨大的采用率,但作为一种技术,React存在于隐藏其自身(相当小的)API下的大量功能。一旦显而易见的区域出现在事件系统中,表面下的很多区域实际上与标准DOM事件系统完全不同。不仅在哪些事件做什么方面,而且在数据被允许在事件处理的哪个阶段持续存在的方面。你可以在这里阅读更多相关内容:

<强> React Event System

答案 1 :(得分:8)

React没有默认行为&#39; onChange&#39;事件。 &#39; onChange&#39;我们在react中看到的有默认行为&#39; onInput&#39;事件。所以回答你的问题,他们两个都没有区别。我在GitHub上提出了一个关于同样问题的问题,这是他们不得不说的:

  

我认为在做出这个决定时(〜4年前?),onInput在浏览器之间不能一致地工作,并且让那些从其他平台上网的人感到困惑,因为他们期望“改变” “每次改变都会触发事件。在React的情况下,这是一个更大的问题,因为如果你不能很快处理更改,受控输入永远不会更新,导致人们认为React被破坏了。所以团队一起调用它来改变。

     

回想起来,填充onInput并保留其名称而不是改变另一个事件的行为可能是一个更好的主意。但是很久以前那艘船已经航行了。我们将来可能会重新审视这个决定,但我会鼓励你将它视为React DOM的一个怪癖(你会很快习惯)。

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

此外,本文还将提供更多见解和默认解决方法&#39; onChange&#39;

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分: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} />;
    }
}

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

我仍然在使用此CustomInput组件方面积累了经验。例如,复选框的行为异常。我要么必须在event.target.checked处理程序中反转onChange,一边用checked将值传递给复选框,或者要当数值通过defaultChecked传递给复选框时,要摆脱这种反转但这会破坏页面上不同位置代表相同状态的多个复选框保持同步。 (在两种情况下,我都没有将onInput处理程序传递给CustomInput的复选框。)

答案 5 :(得分:0)

一个区别似乎是,选择和替换具有相同字符的字符时不会触发onChange,而onInput是。

查看此沙箱:https://codesandbox.io/s/react-onchange-vs-oninput-coggf?file=/src/App.js

  • 在字段中键入“ A”,然后全选并键入“ B”。这将触发4个事件,即2 onChange和2 onInput
  • 现在全选并再次键入“ B”,直到触发新的onInput事件,但没有onChange