主题
受控组件和非受控组件
更新: 9/26/2025字数: 0 字 时长: 0 分钟
一、核心概念区分
1. 受控组件 (Controlled Components)
- 定义:表单数据由 React 组件状态完全控制
- 特点:
- 表单值存储在 state 中
- 通过
onChange事件更新 state - 数据流是单向的(state → 表单)
jsx
function ControlledForm() {
const [value, setValue] = useState("");
const handleChange = (e) => {
setValue(e.target.value);
};
return <input value={value} onChange={handleChange} />;
}2. 非受控组件 (Uncontrolled Components)
- 定义:表单数据由 DOM 自身管理
- 特点:
- 通过 ref 访问 DOM 元素获取值
- 表单保持自己的内部状态
- 更适合与非 React 代码集成
jsx
function UncontrolledForm() {
const inputRef = useRef(null);
const handleSubmit = () => {
console.log(inputRef.current.value);
};
return (
<>
<input ref={inputRef} defaultValue="" />
<button onClick={handleSubmit}>提交</button>
</>
);
}二、技术实现对比
1. 值控制方式
| 特性 | 受控组件 | 非受控组件 |
|---|---|---|
| 值绑定 | value={state} | defaultValue="" |
| 值获取 | 直接从 state 读取 | 需要通过 ref 访问 DOM |
| 状态更新 | onChange 事件触发更新 | DOM 自动管理 |
2. 常见表单元素处理
jsx
// 受控组件示例集合
function ControlledComponents() {
const [text, setText] = useState("");
const [isChecked, setIsChecked] = useState(false);
const [selectedOption, setSelectedOption] = useState("option1");
return (
<>
{/* 文本输入 */}
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
{/* 复选框 */}
<input type="checkbox" checked={isChecked} onChange={(e) => setIsChecked(e.target.checked)} />
{/* 单选按钮 */}
<select value={selectedOption} onChange={(e) => setSelectedOption(e.target.value)}>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
</>
);
}三、选择时机与场景分析
1. 优先使用受控组件的情况
- 需要实时验证输入
- 根据输入动态禁用/启用提交按钮
- 强制特定输入格式
- 实现复杂表单逻辑
jsx
// 实时验证示例
function EmailInput() {
const [email, setEmail] = useState("");
const [isValid, setIsValid] = useState(false);
const handleChange = (e) => {
const value = e.target.value;
setEmail(value);
setIsValid(/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value));
};
return (
<>
<input type="email" value={email} onChange={handleChange} />
{!isValid && <span>请输入有效的邮箱地址</span>}
</>
);
}2. 考虑非受控组件的情况
- 表单非常简单且不需要即时验证
- 需要集成第三方 DOM 库
- 处理大型表单性能敏感时
- 文件上传
<input type="file">(总是非受控)
jsx
// 文件上传示例
function FileUpload() {
const fileInput = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(fileInput.current.files[0]);
};
return (
<form onSubmit={handleSubmit}>
<input type="file" ref={fileInput} />
<button type="submit">上传</button>
</form>
);
}