У React, яка різниця між onChange та onInput?


86

Я спробував знайти відповідь на це, але більшість з них виходять за рамки React, де onChangeспрацьовує розмиття.

Виконуючи різні тести, я не можу сказати, чим відрізняються ці дві події (якщо застосовувати їх до текстового поля). Хтось може пролити це світло?


1
Я відредагував свій пост, щоб бути зрозумілішим. Я говорив конкретно про текстове поле, а не про перемикачі чи прапорці.
ffxsam

Це зовсім хибно, React - це не просто JS. І події поводяться дещо інакше в деяких випадках (наприклад onChange). І ні, вставка тексту в текстове поле (у React) викликає onChangeі onInput. Не соромтеся тестувати на скрипці, і ви побачите.
ffxsam

Для <input> і <textarea> onChange замінює - і, як правило, повинен використовуватися замість - вбудований обробник подій вхідного сигналу DOM.
Роко К. Бульян

Я припускаю, що onChange - це більш безпечна ставка. Я навіть намагався програмно змінити значення текстового поля, думаючи, що може onChangeспрацьовувати, а onInputні, але обидва спрацьовують.
ffxsam 07

Так, тепер, переглянувши трохи React Docs, я бачу, що React робить деякі речі, такі як jQuery, він нормалізує події, і так. onChange здається найкращим способом. І так. React - це не що інше, як JS. Особливої ​​магії немає. Просто правила.
Роко К. Бульян

Відповіді:


79

Здається, реальної різниці немає

React з якихось причин приєднує слухачів Component.onChangeдо element.oninputподії DOM . Див. Примітку в документації до форм:

React docs - Форми

Є більше людей, які здивовані такою поведінкою. Щоб отримати докладнішу інформацію, зверніться до цієї проблеми в програмі відстеження випуску React:

Документуйте, як React's onChange відноситься до onInput # 3964

Цитата з коментарів з цього питання:

Я не розумію, чому React вирішив зробити так, щоб onChange поводився так, як це робить onInput. Наскільки я можу сказати, ми не маємо можливості повернути стару поведінку onChange. Документи стверджують, що це "неправильне ім'я", але насправді це не так, воно спрацьовує, коли відбуваються зміни, лише до тих пір, поки введення також не втратить фокус.

Для перевірки іноді ми не хочемо показувати помилки перевірки, поки вони не закінчать друкувати. А може, ми просто не хочемо повторного відтворення при кожному натисканні клавіші. Зараз єдиний спосіб це зробити за допомогою onBlur, але тепер нам також потрібно перевірити, чи значення змінилося вручну.

Це не така велика угода, але мені здається, що React викинув корисну подію і відхилився від стандартної поведінки, коли вже була подія, яка це робить.

Я погоджуюсь на 100% з коментарем ... Але, мабуть, зміна його зараз принесе більше проблем, ніж вирішує, оскільки вже було написано стільки коду, який покладається на цю поведінку.

React не є частиною офіційної колекції веб-API

Незважаючи на те, що React побудований на базі JS і спостерігає величезний рівень прийняття, оскільки технологія React існує, щоб приховувати цілий ряд функціональних можливостей під власним (досить невеликим) API. Одного разу область, де це очевидно, знаходиться в системі подій, де під поверхнею відбувається багато чого, що насправді кардинально відрізняється від стандартної системи подій DOM. Не лише з точки зору того, які події що роблять, але й з точки зору того, коли дозволяється зберігати дані на якому етапі обробки події. Детальніше про це ви можете прочитати тут:

Система подій React


Останній абзац вводить в оману / не відповідає дійсності.
круїз

1
React - це не фреймворк (де він забезпечує маршрутизацію, постійність, управління мережевим введенням / виводом тощо?), Це бібліотека, яка забезпечує основну абстракцію для маніпулювання деревами відображення за допомогою специфічних платформ (реакція-dom, реакція-рідна, тощо).
круїз

7
Ого, добре Я погоджуюсь, це більше бібліотека, ніж фреймворк, але називати абзац оманливим / неправдивим через це ?? Я також не погоджуюся з думкою, що фреймворк повинен забезпечувати всі аспекти веб-додатків ... Існують, наприклад, фреймворки маршрутизації, або такі речі, як redux, який є структурою державного управління. На мою думку, фреймворк дозволяє заповнювати шматки функціонуючої машини. У випадку з Redux ви заповнюєте редуктори. У випадку Express ви заповнюєте обробники запитів та проміжне програмне забезпечення. І т. Д. Але розрізнення - це, м’яко кажучи, сіра зона.
Stijn de Witt

4
повністю згоден. Суперечки про різницю між бібліотекою та фреймворком - це справді марна трата часу. просто залежить від того, на якому рівні абстракції ви працюєте.
swyx

1
@chadsteele Дякую, приятелю, приємно чути, що це тобі допомогло
Stijn de Witt

21

Різниці немає

React не має поведінки за замовчуванням події 'onChange'. "OnChange", який ми бачимо у реакції, має поведінку за замовчуванням події "onInput". Отже, щоб відповісти на ваше запитання, немає різниці в обох реакціях. Я підняв проблему на GitHub щодо цього самого, і ось що вони мають сказати з цього приводу:

Я думаю, що на час прийняття цього рішення (~ 4 роки тому?), OnInput не працював послідовно між браузерами, і бентежив людей, які заходили в Інтернет з інших платформ, оскільки вони очікували, що подія “зміни” вогонь при кожній зміні. У випадку з React це велика проблема, тому що якщо вам не вдається впоратися зі змінами досить швидко, контрольовані входи ніколи не оновлюються, що змушує людей думати, що React порушений. Тож команда пішла із викликом на Change.

В ретроспективі, можливо, було б кращою ідеєю полізаповнювати 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

Для тих, хто натрапив на цю проблему, шукаючи спосіб прослухати фактичну changeподію на основі DOM , ось як я це зробив (написано на 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прапорцям for.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.