跳到主要内容

非受控组件与受控组件

在 React 中,表单处理是一个常见的任务。为了管理表单数据,React 提供了两种主要方式:非受控组件受控组件。理解这两种方式的区别以及如何选择适合的方式,对于构建高效的表单至关重要。

什么是受控组件?

受控组件是指表单数据由 React 组件管理的组件。换句话说,表单的值由 React 的状态(state)控制。每当用户输入数据时,React 会更新状态,并将新的值传递回表单元素。

受控组件示例

以下是一个简单的受控组件示例:

jsx
import React, { useState } from 'react';

function ControlledInput() {
const [value, setValue] = useState('');

const handleChange = (event) => {
setValue(event.target.value);
};

return (
<input
type="text"
value={value}
onChange={handleChange}
/>
);
}

在这个例子中,value 是一个状态变量,它存储了输入框的当前值。每当用户在输入框中输入内容时,handleChange 函数会被调用,更新 value 状态,并将新的值传递回输入框。

受控组件的优点

  • 完全控制:React 组件完全控制表单数据,可以轻松地验证、格式化或处理数据。
  • 实时更新:由于状态更新是同步的,组件可以实时响应用户输入。

什么是非受控组件?

非受控组件是指表单数据由 DOM 本身管理的组件。React 不直接控制表单的值,而是通过 ref 来获取表单元素的值。

非受控组件示例

以下是一个简单的非受控组件示例:

jsx
import React, { useRef } from 'react';

function UncontrolledInput() {
const inputRef = useRef(null);

const handleSubmit = (event) => {
event.preventDefault();
alert('Input value: ' + inputRef.current.value);
};

return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} />
<button type="submit">Submit</button>
</form>
);
}

在这个例子中,inputRef 是一个引用(ref),它指向输入框的 DOM 元素。当用户提交表单时,handleSubmit 函数会通过 inputRef.current.value 获取输入框的值。

非受控组件的优点

  • 简单易用:对于简单的表单,非受控组件可以减少代码量。
  • 性能优化:由于不需要频繁更新状态,非受控组件在某些情况下可能具有更好的性能。

受控组件与非受控组件的比较

特性受控组件非受控组件
数据管理由 React 状态管理由 DOM 管理
实时更新
代码复杂度较高较低
适用场景需要实时验证或处理的表单简单表单或需要性能优化的场景

实际应用场景

受控组件的应用

假设你正在构建一个注册表单,需要在用户输入时实时验证用户名是否可用。这种情况下,受控组件是理想的选择,因为你可以实时获取输入值并进行验证。

jsx
import React, { useState } from 'react';

function RegistrationForm() {
const [username, setUsername] = useState('');
const [isAvailable, setIsAvailable] = useState(false);

const handleUsernameChange = (event) => {
const newUsername = event.target.value;
setUsername(newUsername);
// 假设这里有一个 API 调用来检查用户名是否可用
checkUsernameAvailability(newUsername).then((available) => {
setIsAvailable(available);
});
};

return (
<form>
<input
type="text"
value={username}
onChange={handleUsernameChange}
/>
{isAvailable ? <span>用户名可用</span> : <span>用户名不可用</span>}
</form>
);
}

非受控组件的应用

假设你正在构建一个简单的搜索框,用户输入关键词后点击按钮进行搜索。这种情况下,非受控组件可能更合适,因为你只需要在用户点击按钮时获取输入值。

jsx
import React, { useRef } from 'react';

function SearchBox() {
const searchRef = useRef(null);

const handleSearch = () => {
const keyword = searchRef.current.value;
// 执行搜索操作
performSearch(keyword);
};

return (
<div>
<input type="text" ref={searchRef} />
<button onClick={handleSearch}>搜索</button>
</div>
);
}

总结

  • 受控组件:表单数据由 React 状态管理,适用于需要实时更新和验证的场景。
  • 非受控组件:表单数据由 DOM 管理,适用于简单表单或需要性能优化的场景。

选择使用受控组件还是非受控组件,取决于你的具体需求。对于复杂的表单,受控组件提供了更多的控制和灵活性;而对于简单的表单,非受控组件可以减少代码量并提高性能。

附加资源与练习

  • 练习 1:尝试将上面的受控组件示例改为非受控组件,并比较两者的代码复杂度。
  • 练习 2:构建一个包含多个输入字段的表单,分别使用受控组件和非受控组件实现,并观察它们的表现。
提示

如果你对 React 的状态管理还不熟悉,建议先学习 React 的基础知识,特别是关于 useStateuseRef 的用法。