Trong React, sự khác biệt giữa onChange và onInput là gì?


86

Tôi đã cố gắng tìm kiếm câu trả lời cho điều này, nhưng hầu hết chúng đều nằm ngoài ngữ cảnh của React, nơi onChangekích hoạt sự mờ ảo.

Khi thực hiện các thử nghiệm khác nhau, tôi dường như không thể biết hai sự kiện này khác nhau như thế nào (khi áp dụng cho một vùng văn bản). Bất cứ ai có thể làm sáng tỏ về điều này?


1
Tôi đã chỉnh sửa bài viết của mình để rõ ràng hơn. Tôi đang nói cụ thể về textarea, không phải các nút radio hay hộp kiểm.
ffxsam

Điều đó hoàn toàn sai, React không chỉ là JS. Và các sự kiện hoạt động hơi khác trong một số trường hợp (chẳng hạn như onChange). Và không, việc dán văn bản trong một vùng văn bản (trong React) sẽ kích hoạt cả onChangeonInput. Hãy tự do thử nghiệm và bạn sẽ thấy.
ffxsam

Đối với <input> và <textareosystem, onChange thay thế - và thường được sử dụng thay vì - trình xử lý sự kiện oninput tích hợp của DOM.
Roko C. Buljan,

Tôi cho rằng onChange là đặt cược an toàn hơn. Tôi thậm chí còn cố gắng lập trình thay đổi giá trị của textarea, nghĩ rằng có thể onChangesẽ kích hoạt và onInputsẽ không, nhưng cả hai đều kích hoạt.
ffxsam

Vâng, bây giờ sau khi xem xét một chút về React Docs, tôi thấy rằng React thực hiện khá nhiều thứ giống như jQuery, nó bình thường hóa các sự kiện và vâng. onChange có vẻ như là một cách ưa thích. Và vâng. React không hơn gì JS. Không có phép thuật đặc biệt. Chỉ là các quy tắc.
Roko C. Buljan,

Câu trả lời:


79

Có vẻ như không có sự khác biệt thực sự

React, vì một số lý do, gắn người nghe Component.onChangevào element.oninputsự kiện DOM . Xem ghi chú trong tài liệu về các biểu mẫu:

Tài liệu phản ứng - Biểu mẫu

Có nhiều người ngạc nhiên bởi hành vi này. Để biết thêm chi tiết, hãy tham khảo vấn đề này trên trình theo dõi vấn đề React:

Ghi lại cách onChange của React liên quan đến onInput # 3964

Trích dẫn các ý kiến ​​về vấn đề đó:

Tôi không hiểu tại sao React lại chọn làm cho onChange hoạt động giống như onInput. Như tôi có thể nói, chúng tôi không có cách nào để khôi phục lại hành vi onChange cũ. Các tài liệu cho rằng đó là một "nhầm lẫn" nhưng không phải vậy, nó hoạt động khi có thay đổi, chỉ là không cho đến khi đầu vào mất tiêu điểm.

Để xác thực, đôi khi chúng tôi không muốn hiển thị lỗi xác thực cho đến khi chúng nhập xong. Hoặc có thể chúng tôi không muốn hiển thị lại mỗi lần nhấn phím. Bây giờ cách duy nhất để làm điều đó là với onBlur nhưng bây giờ chúng ta cũng cần kiểm tra xem giá trị đã thay đổi theo cách thủ công chưa.

Nó không phải là vấn đề lớn, nhưng với tôi thì có vẻ như React đã vứt bỏ một sự kiện hữu ích và đi chệch khỏi hành vi tiêu chuẩn khi đã có một sự kiện thực hiện điều này.

Tôi đồng ý 100% với nhận xét ... Nhưng tôi đoán việc thay đổi nó ngay bây giờ sẽ mang lại nhiều vấn đề hơn là nó giải quyết vì rất nhiều mã đã được viết dựa trên hành vi này.

React không phải là một phần của bộ sưu tập API Web chính thức

Mặc dù React được xây dựng trên nền tảng JS và đã chứng kiến ​​tỷ lệ chấp nhận rất lớn, vì React tồn tại một công nghệ để ẩn rất nhiều chức năng trong API (khá nhỏ) của riêng nó. Một khi khu vực mà điều này hiển nhiên là trong hệ thống sự kiện, nơi có rất nhiều thứ đang diễn ra dưới bề mặt thực sự khác hoàn toàn với hệ thống sự kiện DOM tiêu chuẩn. Không chỉ về mặt sự kiện nào thực hiện những gì, mà còn về thời điểm dữ liệu được phép tồn tại ở giai đoạn xử lý sự kiện nào. Bạn có thể đọc về điều ấy nhiều hơn tại đây:

Hệ thống sự kiện React


Đoạn cuối gây hiểu lầm / không đúng sự thật.
rounce

1
React không phải là một khuôn khổ (nó cung cấp định tuyến, tính bền bỉ, quản lý mạng I / O, v.v.?), Nó là một thư viện cung cấp phần trừu tượng cốt lõi để thao tác cây hiển thị thông qua các phần phụ trợ cụ thể của nền tảng (react-dom, react-native, Vân vân.).
rounce

7
Oh, tốt. Tôi đồng ý rằng nó giống như một thư viện hơn là một khuôn khổ, nhưng để gọi đoạn văn là sai lệch / không đúng sự thật vì điều đó ?? Tôi cũng không đồng ý với quan điểm rằng một khung công tác phải cung cấp tất cả các khía cạnh của một ứng dụng web ... Ví dụ, có các khung công tác định tuyến, hoặc những thứ như redux là một khung quản lý nhà nước. Theo suy nghĩ của tôi, một khuôn khổ cho phép bạn điền vào các phần của một cỗ máy đang hoạt động. Trong trường hợp của Redux, bạn điền vào các bộ giảm bớt. Trong trường hợp Express, bạn điền vào các trình xử lý yêu cầu và phần mềm trung gian. Vv. Nhưng sự khác biệt là một khu vực màu xám để nói rằng ít nhất.
Stijn de Witt,

4
hoàn toàn đồng ý. tranh luận về sự khác biệt giữa thư viện và khuôn khổ thực sự là một sự lãng phí thời gian. chỉ phụ thuộc vào mức độ trừu tượng mà bạn đang làm việc.
swyx

1
@chadsteele Thanks buddy, tuyệt vời để nghe nó giúp bạn
Stijn de Witt

21

Không có sự khác biệt

React không có hành vi của sự kiện 'onChange' mặc định. 'OnChange' mà chúng ta thấy trong phản ứng có hành vi của sự kiện 'onInput' mặc định. Vì vậy, để trả lời câu hỏi của bạn, không có sự khác biệt trong phản ứng của cả hai. Tôi đã nêu một vấn đề trên GitHub về vấn đề tương tự và đây là những gì họ phải nói về nó:

Tôi nghĩ rằng tại thời điểm quyết định này được đưa ra (~ 4 năm trước?), OnInput không hoạt động nhất quán giữa các trình duyệt và gây nhầm lẫn cho những người truy cập web từ các nền tảng khác, vì họ mong đợi sự kiện "thay đổi" chữa cháy cho mọi thay đổi. Trong trường hợp của React, đó là một vấn đề lớn hơn vì nếu bạn không xử lý thay đổi đủ sớm, các đầu vào được kiểm soát sẽ không bao giờ cập nhật, khiến mọi người nghĩ rằng React đã bị hỏng. Vì vậy, nhóm đã gọi nó là onChange.

Nhìn lại, có thể là một ý tưởng tốt hơn nếu điền onInput và giữ nguyên tên của nó thay vì thay đổi hành vi của một sự kiện khác. Nhưng con tàu đó đã ra khơi từ lâu. Chúng tôi có thể xem xét lại quyết định này trong tương lai, nhưng tôi chỉ khuyến khích bạn coi nó như một phần mềm của React DOM (bạn sẽ làm quen khá nhanh).

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

Ngoài ra bài viết này sẽ cung cấp thêm cái nhìn sâu sắc. Là một giải pháp thay thế cho việc thiếu 'onChange' mặc định, bài viết đề xuất nghe sự kiện 'onBlur'.

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


3

Gần đây, tôi đã gặp lỗi onChangekhông cho phép sao chép và dán vào trường nhập trên IE11. Trong khi onInputsự kiện sẽ cho phép hành vi đó. Tôi không thể tìm thấy bất kỳ tài liệu nào mô tả điều này trong tài liệu, nhưng điều đó cho thấy có sự khác biệt giữa hai (dự kiến ​​hoặc không).


2

Như bạn có thể thấy trong các bình luận khác nhau ở đây, React đối xử với onChange và onInput giống nhau, thay vì tranh luận về giá trị của quyết định này. Đây là giải pháp.

Sử dụng onBlur khi bạn không muốn xử lý các chỉnh sửa của người dùng cho đến khi chúng hoàn tất. :)


1

Đối với bất kỳ ai gặp phải vấn đề này đang tìm cách lắng nghe sự kiện thực tế, dựa trên DOM change, đây là cách tôi đã thực hiện (được viết bằng 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} />;
    }
}

Vui lòng cho tôi biết nếu bạn thấy cách cải thiện phương pháp này hoặc gặp sự cố với nó. Không giống như blur, changesự kiện cũng được kích hoạt khi người dùng nhấn enter và chỉ được kích hoạt nếu giá trị thực sự thay đổi.

Tôi vẫn đang tích lũy kinh nghiệm với CustomInputthành phần này . Ví dụ, các hộp kiểm hoạt động kỳ lạ. Tôi phải đảo ngược event.target.checkedtrong onChangetrình xử lý trong khi chuyển giá trị vào hộp kiểm với checkedhoặc loại bỏ sự đảo ngược này khi chuyển giá trị vào hộp kiểm với defaultCheckednhưng điều này sau đó phá vỡ rằng một số hộp kiểm đại diện cho cùng một trạng thái ở các vị trí khác nhau trên trang vẫn đồng bộ hóa . (Trong cả hai trường hợp, tôi đã không chuyển một onInputtrình xử lý vào CustomInputhộp kiểm cho.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.