HOWTO · React

在 React 中使用 onChange 事件

onChange 是 React 中最常见的输入事件之一。本文将帮助你了解它的工作原理。

本页内容

React 的 onChange 属性可让组件响应表单控件的变化。事件处理函数读取发生变化的控件值,并更新用于显示该值的状态。React 的 onChange 并不等同于原生 HTML 的 onchange 属性:React 通过自己的事件系统处理表单变化,其行为适用于 React 控件。

当组件需要管理当前表单值、验证该值,或在界面其他位置使用它时,可以使用受控输入。基本做法是将状态值传给控件,并在其 onChange 处理函数中更新状态。

理解 onChange 事件

使用 JSX 属性 onChange,即可为 input、textarea 或 select 添加事件处理函数。对于文本框和选择框,读取 event.target.value;对于复选框,读取布尔值 event.target.checked。随后,处理函数会更新与该控件关联的状态。

在受控表单控件中,显示的值来自状态。处理函数更新状态后,React 会用新值重新渲染控件,使界面与组件数据保持同步。如果组件在交互过程中无需管理控件值,可以选择非受控控件。

使用 onChange 处理文本输入

对于文本输入框,应将字符串保存在状态中,通过 value 传给控件,并根据事件更新状态。假设类组件的状态中包含 name,可以这样编写 JSX 控件:<input value={this.state.name} onChange={event => this.setState({ name: event.target.value })} />。状态更新后,显示的文本会随每次编辑而变化。输入框在整个使用期间都应保持字符串类型的状态值。

下面的可运行 JavaScript 单独演示文本框、复选框和选择框的处理函数逻辑。它通过简单的状态设置函数展示各处理函数读取的事件属性,并不会渲染 React 控件。本文中的 JSX 则展示如何将这些值连接到 React 受控控件。输出块中的可见标签保持英文;它们展示的是示例记录的事件值。

let name = '';
let subscribed = false;
let category = 'books';

const setName = (value) => { name = value; };
const setSubscribed = (value) => { subscribed = value; };
const setCategory = (value) => { category = value; };

const handleNameChange = (event) => setName(event.target.value);
const handleSubscribedChange = (event) => setSubscribed(event.target.checked);
const handleCategoryChange = (event) => setCategory(event.target.value);

handleNameChange({ target: { value: 'Ada' } });
handleSubscribedChange({ target: { checked: true } });
handleCategoryChange({ target: { value: 'music' } });

console.log(`Name: ${name}`);
console.log(`Subscribed: ${subscribed}`);
console.log(`Category: ${category}`);
Name: Ada
Subscribed: true
Category: music

在 React 组件中,这个可运行示例里的设置函数对应状态更新。控件显示的值来自该状态,因此 React 可以让视图与数据保持同步。

使用复选框

复选框表示一个布尔选择,因此应通过 checked 控制其选中状态,并在处理函数中读取 event.target.checked。在类组件中,可以这样设置复选框:checked={this.state.subscribed} 和 onChange={event => this.setState({ subscribed: event.target.checked })}。复选框的 value 是提交表单时使用的值,并不表示用户是否选中了它。

使用 onChange 处理下拉选择框

对于选择控件,应通过 value 传入当前选中状态,并从 event.target.value 读取新选项。例如,可以使用 <select value={this.state.category} onChange={event => this.setState({ category: event.target.value })}><option value="books">Books</option><option value="music">Music</option></select>。选项的值会存入状态,可能与用户看到的标签不同。更新状态后,选中项及依赖该选项的界面都会以同一数据源为准。

使用 onChange 的最佳实践

让处理函数专注于读取事件并更新相关状态。根据表单的实际需求安排验证方式:例如,为了即时反馈,可以在用户输入时验证;如果输入过程中提供反馈会造成干扰,则可以在提交时验证。确保 value 属性与对应状态使用一致的类型,并使用 checked 管理复选框状态。

当处理函数会启动耗时操作时,例如筛选大型数据集或发送搜索请求,防抖可能有所帮助。防抖会延迟响应,也不会自动阻止 React 渲染,因此只有在工作负载和用户体验都适合时才使用。每次按键都更新受控状态是常见做法。

通过程序直接更改输入控件的 DOM 值属于进阶场景。直接赋值本身并不能保证 React 会观察到变化或调用预期的处理函数。优先更新控制该输入框的状态。如果外部代码必须与表单控件交互,尽可能使用组件的公开接口,并在该集成场景中验证行为;setNativeValue 之类的辅助函数名称并不代表通用的 React API,也不是有保证的修复方法。

总结

React 的 onChange 处理函数将用户编辑与组件状态连接起来。文本和选择控件读取 value,复选框读取 checked,然后根据更新后的状态渲染受控控件。应根据表单需求决定如何验证以及是否使用防抖,不要将它们当作一概适用的规则。

常见问题

  1. React 中的 onChange 有什么作用? 表单控件发生变化时,它会调用处理函数,让组件读取新值并更新数据或状态。

  2. 如何处理文本输入框? 将字符串状态值传给输入框的 value 属性,并在 onChange 中根据 event.target.value 更新该状态。

  3. 如何处理复选框? 通过 checked 属性使用布尔状态控制复选框,并根据 event.target.checked 更新该状态。

  4. 如何处理 select 元素? 将状态设置为它的 value,并在选项变化时根据 event.target.value 更新该状态。

  5. 每个 onChange 处理函数都应该使用防抖吗? 不应该。只有当处理函数会启动耗时操作时,才考虑使用防抖;每次状态更新都不需要防抖,而且防抖也不能保证减少渲染次数。

  6. 为什么通过程序更改值可能不会调用我的处理函数? 直接给 DOM 值赋值不一定会触发 React 的变化处理。请更新控制输入框的状态,或使用组件支持的接口。